diff options
Diffstat (limited to 'Ministro/src/eu')
6 files changed, 0 insertions, 1561 deletions
diff --git a/Ministro/src/eu/licentia/necessitas/ministro/IMinistro.aidl b/Ministro/src/eu/licentia/necessitas/ministro/IMinistro.aidl deleted file mode 100644 index ec6a240..0000000 --- a/Ministro/src/eu/licentia/necessitas/ministro/IMinistro.aidl +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (c) 2011, BogDan Vatra <bog_dan_ro@yahoo.com> - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the BogDan Vatra <bog_dan_ro@yahoo.com> nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY BogDan Vatra <bog_dan_ro@yahoo.com> ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package eu.licentia.necessitas.ministro; - -import eu.licentia.necessitas.ministro.IMinistroCallback; - -interface IMinistro -{ - /** - * Check/download required libs to run the application - * - * param callback - interface used by the service to notify the client when it has the libs - * param modules - Qt modules you want to check - * param appName - Application name, used to show more informations to user - * param ministroApiLevel - Ministro api level, used to check ministro service compatibility. - * Current API Level is 1 !!! - * param mecessitasApiLevel - Necessitas api level, used to download the right platform plugin. - * Current API Level is 1 !!! - */ - - void checkModules(in IMinistroCallback callback, in String[] modules, in String appName, in int ministroApiLevel, in int necessitasApiLevel); -} diff --git a/Ministro/src/eu/licentia/necessitas/ministro/IMinistroCallback.aidl b/Ministro/src/eu/licentia/necessitas/ministro/IMinistroCallback.aidl deleted file mode 100644 index a41a210..0000000 --- a/Ministro/src/eu/licentia/necessitas/ministro/IMinistroCallback.aidl +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (c) 2011, BogDan Vatra <bog_dan_ro@yahoo.com> - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the BogDan Vatra <bog_dan_ro@yahoo.com> nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY BogDan Vatra <bog_dan_ro@yahoo.com> ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package eu.licentia.necessitas.ministro; - -oneway interface IMinistroCallback { - /** - * This method is called by the Ministro service back into the application which - * implements this interface. - * - * <p>The method allows notifying the application about the result of the library - * lookup. In case the <code>errorCode</code> argument is 0, the called application - * can start without problems.</p> - * - * param in - libs, you have to load before load the application - * param in - evnVars, tab separated environment variables - * param in - params, tab separated paras which should be passed to the application - * param in - errorCode, the error number, the application should check the error code before starts - * - 0 no error - * - 1 no qt libs found - * - xxx - * param in - errorMessage, the error message (where available, translated into phone language). - */ - - void libs(in String[] libs,in String environmentVariables, in String applicationParams, in int errorCode, in String errorMessage); -} diff --git a/Ministro/src/eu/licentia/necessitas/ministro/Library.java b/Ministro/src/eu/licentia/necessitas/ministro/Library.java deleted file mode 100644 index 899b797..0000000 --- a/Ministro/src/eu/licentia/necessitas/ministro/Library.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - Copyright (c) 2011, BogDan Vatra <bog_dan_ro@yahoo.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -package eu.licentia.necessitas.ministro; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - - -class Library -{ - public String name = null; - public String filePath = null; - public String[] depends = null; - public String[] replaces = null; - public NeedsStruct[] needs = null; - public int level=0; - public long size = 0; - public String sha1 = null; - public String url; - - public static String[] getLibNames(Element libNode) - { - if (libNode == null) - return null; - NodeList list=libNode.getElementsByTagName("lib"); - ArrayList<String> libs = new ArrayList<String>(); - for (int i=0;i<list.getLength();i++) - { - if (list.item(i).getNodeType() != Node.ELEMENT_NODE) - continue; - Element lib=(Element)list.item(i); - if (lib!=null) - libs.add(lib.getAttribute("name")); - } - String[] strings = new String[libs.size()]; - return libs.toArray(strings); - } - - public static NeedsStruct[] getNeeds(Element libNode) - { - if (libNode == null) - return null; - NodeList list=libNode.getElementsByTagName("item"); - ArrayList<NeedsStruct> needs = new ArrayList<NeedsStruct>(); - - for (int i=0;i<list.getLength();i++) - { - if (list.item(i).getNodeType() != Node.ELEMENT_NODE) - continue; - Element lib=(Element)list.item(i); - if (lib!=null) - { - NeedsStruct need=new NeedsStruct(); - need.name=lib.getAttribute("name"); - need.filePath=lib.getAttribute("file"); - need.url=lib.getAttribute("url"); - need.sha1=lib.getAttribute("sha1"); - need.size=Long.valueOf(lib.getAttribute("size")); - needs.add(need); - } - } - NeedsStruct[] _needs = new NeedsStruct[needs.size()]; - return needs.toArray(_needs); - } - - public static Library getLibrary(Element libNode, boolean includeNeed) - { - Library lib= new Library(); - lib.name=libNode.getAttribute("name"); - lib.sha1=libNode.getAttribute("sha1").toUpperCase(); - lib.filePath=libNode.getAttribute("file"); - lib.url=libNode.getAttribute("url"); - try - { - lib.level=Integer.parseInt(libNode.getAttribute("level")); - } catch (Exception e) { - e.printStackTrace(); - } - - try - { - lib.size=Long.parseLong(libNode.getAttribute("size")); - } catch (Exception e) { - e.printStackTrace(); - } - NodeList list=libNode.getElementsByTagName("depends"); - for (int i=0;i<list.getLength();i++) - { - if (list.item(i).getNodeType() != Node.ELEMENT_NODE) - continue; - lib.depends=getLibNames((Element) list.item(i)); - break; - } - list=libNode.getElementsByTagName("replaces"); - for (int i=0;i<list.getLength();i++) - { - if (list.item(i).getNodeType() != Node.ELEMENT_NODE) - continue; - lib.replaces=getLibNames((Element) list.item(i)); - break; - } - - if (!includeNeed) // don't waste time. - return lib; - - list=libNode.getElementsByTagName("needs"); - for (int i=0;i<list.getLength();i++) - { - if (list.item(i).getNodeType() != Node.ELEMENT_NODE) - continue; - lib.needs=getNeeds((Element) list.item(i)); - break; - } - return lib; - } - - public static String convertToHex(byte[] data) - { - StringBuffer buf = new StringBuffer(); - for (int i = 0; i < data.length; i++) - { - int halfbyte = (data[i] >>> 4) & 0x0F; - int two_halfs = 0; - do - { - if ((0 <= halfbyte) && (halfbyte <= 9)) - buf.append((char) ('0' + halfbyte)); - else - buf.append((char) ('a' + (halfbyte - 10))); - halfbyte = data[i] & 0x0F; - } while(two_halfs++ < 1); - } - return buf.toString(); - } - - public static boolean checkCRC(String fileName, String sha1) throws IOException - { - try { - byte[] tmp = new byte[2048]; - MessageDigest digester = MessageDigest.getInstance("SHA-1"); - int downloaded; - FileInputStream inFile = new FileInputStream(new File(fileName)); - while ((downloaded = inFile.read(tmp)) != -1) - { - digester.update(tmp, 0, downloaded); - } - return sha1.equalsIgnoreCase(convertToHex(digester.digest())); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - return false; - } - - public static String mkdirParents(String rootPath, String filePath, int skip) - { - String[] paths=filePath.split("/"); - String path = ""; - for (int pit=0;pit<paths.length-skip;pit++) - { - if (paths[pit].length()==0) - continue; - path+="/"+paths[pit]; - File dir=new File(rootPath+path); - dir.mkdir(); - MinistroActivity.nativeChmode(rootPath+path, 0755); - } - return rootPath+path; - } - - public static void removeAllFiles(String path) - { - String files[]=new File(path).list(); - if (!path.endsWith("/")) - path+="/"; - for (int i=0;i<files.length;i++) - new File(path+files[i]).delete(); - } -}; - -class NeedsStruct -{ - public String name = null; - public String filePath = null; - public String sha1 = null; - public String url; - public long size = 0; -};
\ No newline at end of file diff --git a/Ministro/src/eu/licentia/necessitas/ministro/MinistroActivity.java b/Ministro/src/eu/licentia/necessitas/ministro/MinistroActivity.java deleted file mode 100644 index f999274..0000000 --- a/Ministro/src/eu/licentia/necessitas/ministro/MinistroActivity.java +++ /dev/null @@ -1,618 +0,0 @@ -/* - Copyright (c) 2011, BogDan Vatra <bog_dan_ro@yahoo.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -package eu.licentia.necessitas.ministro; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import org.apache.http.client.ClientProtocolException; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.NotificationManager; -import android.app.ProgressDialog; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.IBinder; -import android.provider.Settings; - -public class MinistroActivity extends Activity { - - public native static int nativeChmode(String filepath, int mode); - private static final String DOMAIN_NAME="http://files.kde.org/necessitas/ministro/"; - - private String[] m_modules; - private int m_id=-1; - private String m_qtLibsRootPath; - - private void checkNetworkAndDownload(final boolean update) - { - if (isOnline(this)) - new CheckLibraries().execute(update); - else - { - AlertDialog.Builder builder = new AlertDialog.Builder(MinistroActivity.this); - builder.setMessage("Ministro requires network access. Enable mobile network or Wi-Fi to download data."); - builder.setCancelable(true); - builder.setNeutralButton("Setting", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - final ProgressDialog m_dialog = ProgressDialog.show(MinistroActivity.this, null, "Waiting for network connection", true, true, new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - finishMe(); - } - }); - getApplication().registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (isOnline(MinistroActivity.this)) - { - getApplication().unregisterReceiver(this); - runOnUiThread(new Runnable() { - @Override - public void run() { - m_dialog.dismiss(); - new CheckLibraries().execute(update); - } - }); - } - } - }, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); - startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS)); - dialog.dismiss(); - } - }); - builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }); - builder.setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - finishMe(); - } - }); - AlertDialog alert = builder.create(); - alert.show(); - } - } - - private ServiceConnection m_ministroConnection=new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - if (getIntent().hasExtra("id") && getIntent().hasExtra("modules")) - { - m_id=getIntent().getExtras().getInt("id"); - m_modules=getIntent().getExtras().getStringArray("modules"); - AlertDialog.Builder builder = new AlertDialog.Builder(MinistroActivity.this); - builder.setMessage(getIntent().getExtras().getString("name")+ - " needs extra libraries to run.\nDo you want to download them now?") - .setCancelable(false) - .setPositiveButton("Yes", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.dismiss(); - checkNetworkAndDownload(false); - } - }) - .setNegativeButton("No", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - finishMe(); - } - }); - AlertDialog alert = builder.create(); - alert.show(); - } - else - checkNetworkAndDownload(true); - } - - @Override - public void onServiceDisconnected(ComponentName name) { - m_ministroConnection = null; - } - }; - - void finishMe() - { - if (-1 != m_id && null != MinistroService.instance()) - MinistroService.instance().retrievalFinished(m_id); - else - { - NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - nm.cancelAll(); - } - finish(); - } - - private static URL getVersionUrl(Context c) throws MalformedURLException - { - return new URL(DOMAIN_NAME+MinistroService.getRepository(c)+"/android/"+android.os.Build.CPU_ABI+"/android-"+android.os.Build.VERSION.SDK_INT+"/versions.xml"); - } - - private static URL getLibsXmlUrl(Context c, double version) throws MalformedURLException - { - return new URL(DOMAIN_NAME+MinistroService.getRepository(c)+"/android/"+android.os.Build.CPU_ABI+"/android-"+android.os.Build.VERSION.SDK_INT+"/libs-"+version+".xml"); - } - - public static boolean isOnline(Context c) - { - ConnectivityManager cm = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo netInfo = cm.getActiveNetworkInfo(); - if (netInfo != null && netInfo.isConnectedOrConnecting()) - return true; - return false; - } - - public static double downloadVersionXmlFile(Context c, boolean checkOnly) - { - if (!isOnline(c)) - return-1; - try - { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document dom = null; - Element root = null; - URLConnection connection = getVersionUrl(c).openConnection(); - dom = builder.parse(connection.getInputStream()); - root = dom.getDocumentElement(); - root.normalize(); - double version = Double.valueOf(root.getAttribute("latest")); - if ( MinistroService.instance().getVersion() >= version ) - return MinistroService.instance().getVersion(); - - if (checkOnly) - return version; - - connection = getLibsXmlUrl(c, version).openConnection(); - connection.setRequestProperty("Accept-Encoding", "gzip,deflate"); - File file= new File(MinistroService.instance().getVersionXmlFile()); - file.delete(); - FileOutputStream outstream = new FileOutputStream(MinistroService.instance().getVersionXmlFile()); - InputStream instream = connection.getInputStream(); - byte[] tmp = new byte[2048]; - int downloaded; - while ((downloaded = instream.read(tmp)) != -1) { - outstream.write(tmp, 0, downloaded); - } - outstream.close(); - MinistroService.instance().refreshLibraries(false); - return version; - } catch (ClientProtocolException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } catch (IllegalStateException e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - return -1; - } - - private class DownloadManager extends AsyncTask<Library, Integer, Long> { - private ProgressDialog m_dialog = null; - private String m_status = "Start downloading ..."; - private int m_totalSize=0, m_totalProgressSize=0; - - @Override - protected void onPreExecute() { - m_dialog = new ProgressDialog(MinistroActivity.this); - m_dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); - m_dialog.setTitle("Downloading Qt libraries"); - m_dialog.setMessage(m_status); - m_dialog.setCancelable(true); - m_dialog.setOnCancelListener(new DialogInterface.OnCancelListener(){ - @Override - public void onCancel(DialogInterface dialog) { - DownloadManager.this.cancel(false); - finishMe(); - } - }); - m_dialog.show(); - super.onPreExecute(); - } - - private boolean DownloadItem(String url, String file, long size, String fileSha1) throws NoSuchAlgorithmException, MalformedURLException, IOException - { - MessageDigest digester = MessageDigest.getInstance("SHA-1"); - URLConnection connection = new URL(url).openConnection(); - connection.setRequestProperty("Accept-Encoding", "gzip,deflate"); - Library.mkdirParents(m_qtLibsRootPath, file, 1); - String filePath=m_qtLibsRootPath+file; - int progressSize=0; - try - { - FileOutputStream outstream = new FileOutputStream(filePath); - InputStream instream = connection.getInputStream(); - int downloaded; - byte[] tmp = new byte[2048]; - int oldProgress=-1; - while ((downloaded = instream.read(tmp)) != -1) { - if (isCancelled()) - break; - progressSize+=downloaded; - m_totalProgressSize+=downloaded; - digester.update(tmp, 0, downloaded); - outstream.write(tmp, 0, downloaded); - int progress=(int)(progressSize*100/size); - if (progress!=oldProgress) - { - publishProgress(progress - , m_totalProgressSize); - oldProgress = progress; - } - } - String sha1 = Library.convertToHex(digester.digest()); - if (sha1.equalsIgnoreCase(fileSha1)) - { - outstream.close(); - nativeChmode(filePath, 0644); - MinistroService.instance().refreshLibraries(false); - return true; - } - outstream.close(); - File f = new File(filePath); - f.delete(); - } catch (Exception e) { - e.printStackTrace(); - File f = new File(filePath); - f.delete(); - } - m_totalProgressSize-=progressSize; - return false; - } - @Override - protected Long doInBackground(Library... params) { - try { - for (int i=0;i<params.length;i++) - { - m_totalSize+=params[i].size; - if (null != params[i].needs) - for (int j=0;j<params[i].needs.length;j++) - m_totalSize+=params[i].needs[j].size; - } - - m_dialog.setMax(m_totalSize); - int lastId=-1; - for (int i=0;i<params.length;i++) - { - if (isCancelled()) - break; - synchronized (m_status) { - m_status=params[i].name+" "; - } - publishProgress(0, m_totalProgressSize); - if (!DownloadItem(params[i].url, params[i].filePath, params[i].size, params[i].sha1)) - { - // sometimes for some reasons which I don't understand, Ministro receives corrupt data, so let's give it another chance. - if (i == lastId) - break; - lastId=i; - --i; - continue; - } - - lastId=-1; - if (null != params[i].needs) - for (int j=0;j<params[i].needs.length;j++) - { - synchronized (m_status) { - m_status=params[i].needs[j].name+" "; - } - publishProgress(0, m_totalProgressSize); - if (!DownloadItem(params[i].needs[j].url, params[i].needs[j].filePath, params[i].needs[j].size, params[i].needs[j].sha1)) - { - // sometimes for some reasons which I don't understand, Ministro receives corrupt data, so let's give it another chance. - if (j == lastId) - break; - lastId=j; - --j; - continue; - } - lastId=-1; - } - } - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - @Override - protected void onProgressUpdate(Integer... values) { - synchronized (m_status) { - m_dialog.setMessage(m_status+values[0]+"%"); - m_dialog.setProgress(values[1]); - } - super.onProgressUpdate(values); - } - - @Override - protected void onPostExecute(Long result) { - super.onPostExecute(result); - if (m_dialog != null) - { - m_dialog.dismiss(); - m_dialog = null; - } - finishMe(); - } - } - - private class CheckLibraries extends AsyncTask<Boolean, Void, Double> { - - private ProgressDialog dialog = null; - private ArrayList<Library> newLibs = new ArrayList<Library>(); - private String m_message; - @Override - protected void onPreExecute() { - runOnUiThread(new Runnable() { - @Override - public void run() { - dialog = ProgressDialog.show(MinistroActivity.this, null, - "Checking libraries. Please wait...", true, true); - } - }); - super.onPreExecute(); - } - - @Override - protected Double doInBackground(Boolean... update) { - double version=0.0; - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document dom = null; - Element root = null; - double oldVersion=MinistroService.instance().getVersion(); - if (update[0] || MinistroService.instance().getVersion()<0) - version = downloadVersionXmlFile(MinistroActivity.this, false); - else - version = MinistroService.instance().getVersion(); - - ArrayList<Library> libraries; - if (update[0]) - { - if (oldVersion!=version) - libraries = MinistroService.instance().getDownloadedLibraries(); - else - return version; - } - else - libraries = MinistroService.instance().getAvailableLibraries(); - ArrayList<String> notFoundModules = new ArrayList<String>(); - if (m_modules!=null) - { - ArrayList<String> requiredModules = new ArrayList<String>(); - Collections.addAll(requiredModules, m_modules); - MinistroService.instance().checkModules(requiredModules, notFoundModules); - } - dom = builder.parse(new FileInputStream(MinistroService.instance().getVersionXmlFile())); - - factory = DocumentBuilderFactory.newInstance(); - builder = factory.newDocumentBuilder(); - root = dom.getDocumentElement(); - root.normalize(); - - // extract device root certificates - SharedPreferences preferences=getSharedPreferences("Ministro", MODE_PRIVATE); - if (!preferences.getString("CODENAME", "").equals(android.os.Build.VERSION.CODENAME) || - !preferences.getString("INCREMENTAL", "").equals(android.os.Build.VERSION.INCREMENTAL) || - !preferences.getString("RELEASE", "").equals(android.os.Build.VERSION.RELEASE)) - { - m_message = "Extracting SSL root certificates. Please wait..."; - publishProgress((Void[])null); - String environmentVariables=root.getAttribute("environmentVariables"); - environmentVariables=environmentVariables.replaceAll("MINISTRO_PATH", ""); - String environmentVariablesList[]=environmentVariables.split("\t"); - for (int i=0;i<environmentVariablesList.length;i++) - { - String environmentVariable[]=environmentVariablesList[i].split("="); - if (environmentVariable[0].equals("MINISTRO_SSL_CERTS_PATH")) - { - String path=Library.mkdirParents(getFilesDir().getAbsolutePath(),environmentVariable[1], 0); - Library.removeAllFiles(path); - try { - KeyStore ks= KeyStore.getInstance(KeyStore.getDefaultType()); - FileInputStream instream = new FileInputStream(new File("/system/etc/security/cacerts.bks")); - ks.load(instream, null); - for (Enumeration<String> aliases = ks.aliases(); aliases.hasMoreElements(); ) { - String aName = aliases.nextElement(); - try{ - X509Certificate cert=(X509Certificate) ks.getCertificate(aName); - if (null==cert) - continue; - String filePath=path+"/"+cert.getType()+"_"+cert.hashCode()+".der"; - FileOutputStream outstream = new FileOutputStream(new File(filePath)); - byte buff[]=cert.getEncoded(); - outstream.write(buff, 0, buff.length); - outstream.close(); - nativeChmode(filePath, 0644); - } - catch(KeyStoreException e) - { - e.printStackTrace(); - } - catch(Exception e) - { - e.printStackTrace(); - } - } - } catch (KeyStoreException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (CertificateException e) { - e.printStackTrace(); - } - SharedPreferences.Editor editor= preferences.edit(); - editor.putString("CODENAME",android.os.Build.VERSION.CODENAME); - editor.putString("INCREMENTAL", android.os.Build.VERSION.INCREMENTAL); - editor.putString("RELEASE", android.os.Build.VERSION.RELEASE); - editor.commit(); - break; - } - } - } - - Node node = root.getFirstChild(); - while(node != null) - { - if (node.getNodeType() == Node.ELEMENT_NODE) - { - Library lib= Library.getLibrary((Element)node, true); - if (update[0]) - { // check for updates - for (int j=0;j<libraries.size();j++) - if (libraries.get(j).name.equals(lib.name)) - { - newLibs.add(lib); - break; - } - } - else - {// download missing libraries - for(String module : notFoundModules) - if (module.equals(lib.name)) - { - newLibs.add(lib); - break; - } - } - } - - // Workaround for an unbelievable bug !!! - try { - node = node.getNextSibling(); - } catch (Exception e) { - e.printStackTrace(); - break; - } - } - return version; - } catch (ClientProtocolException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } catch (IllegalStateException e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - return -1.; - } - - @Override - protected void onProgressUpdate(Void... nothing) { - dialog.setMessage(m_message); - super.onProgressUpdate(nothing); - } - @Override - protected void onPostExecute(Double result) { - if (null != dialog) - { - dialog.dismiss(); - dialog = null; - } - if (newLibs.size()>0 && result>0) - { - Library[] libs = new Library[newLibs.size()]; - libs = newLibs.toArray(libs); - new DownloadManager().execute(libs); - } - else - finishMe(); - super.onPostExecute(result); - } - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.main); - m_qtLibsRootPath = getFilesDir().getAbsolutePath()+"/qt/"; - File dir=new File(m_qtLibsRootPath); - dir.mkdirs(); - nativeChmode(m_qtLibsRootPath, 0755); - bindService(new Intent("eu.licentia.necessitas.ministro.IMinistro"), m_ministroConnection, Context.BIND_AUTO_CREATE); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - unbindService(m_ministroConnection); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - //Avoid activity from being destroyed/created - super.onConfigurationChanged(newConfig); - } - - static { - System.loadLibrary("chmode"); - } -} diff --git a/Ministro/src/eu/licentia/necessitas/ministro/MinistroConfigActivity.java b/Ministro/src/eu/licentia/necessitas/ministro/MinistroConfigActivity.java deleted file mode 100644 index 294affc..0000000 --- a/Ministro/src/eu/licentia/necessitas/ministro/MinistroConfigActivity.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (c) 2011, BogDan Vatra <bog_dan_ro@yahoo.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -package eu.licentia.necessitas.ministro; - -import android.app.Activity; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.ArrayAdapter; -import android.widget.Spinner; -import android.widget.Toast; - -public class MinistroConfigActivity extends Activity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - // TODO Auto-generated method stub - super.onCreate(savedInstanceState); - setContentView(R.layout.repoconfig); - Spinner s = (Spinner) findViewById(R.id.spinner); - ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource( - this, R.array.repositories, android.R.layout.simple_spinner_item); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - s.setAdapter(adapter); - s.setSelection(adapter.getPosition(MinistroService.getRepository(this))); - s.setOnItemSelectedListener(new OnItemSelectedListener(){ - @Override - public void onItemSelected(AdapterView<?> parent, View view, int pos, - long id) { - // TODO Auto-generated method stub - Toast.makeText(parent.getContext(), "Ministro will use " + - parent.getItemAtPosition(pos).toString()+" repository", Toast.LENGTH_LONG).show(); - MinistroService.setRepository(MinistroConfigActivity.this, parent.getItemAtPosition(pos).toString()); - } - - @Override - public void onNothingSelected(AdapterView<?> arg0) { - // TODO Auto-generated method stub - } - }); - } - - @Override - protected void onDestroy() { - NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - int icon = R.drawable.icon; - CharSequence tickerText = "Ministro repository changed"; // ticker-text - long when = System.currentTimeMillis(); // notification time - Context context = getApplicationContext(); // application Context - CharSequence contentTitle = "Ministro update"; // expanded message title - CharSequence contentText = "Ministro repository changed tap to update."; // expanded message text - - Intent notificationIntent = new Intent(this, MinistroActivity.class); - PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); - - // the next two lines initialize the Notification, using the configurations above - Notification notification = new Notification(icon, tickerText, when); - notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); - notification.defaults |= Notification.DEFAULT_SOUND; - notification.defaults |= Notification.DEFAULT_VIBRATE; - notification.defaults |= Notification.DEFAULT_LIGHTS; - try{ - nm.notify(1, notification); - }catch(Exception e) - { - e.printStackTrace(); - } - super.onDestroy(); - } -}
\ No newline at end of file diff --git a/Ministro/src/eu/licentia/necessitas/ministro/MinistroService.java b/Ministro/src/eu/licentia/necessitas/ministro/MinistroService.java deleted file mode 100644 index ed41368..0000000 --- a/Ministro/src/eu/licentia/necessitas/ministro/MinistroService.java +++ /dev/null @@ -1,545 +0,0 @@ -/* - Copyright (c) 2011, BogDan Vatra <bog_dan_ro@yahoo.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -package eu.licentia.necessitas.ministro; - -import java.io.File; -import java.io.FileInputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.AsyncTask; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; - -public class MinistroService extends Service { - private static final String TAG = "MinistroService"; - - private static final String MINISTRO_CHECK_UPDATES_KEY="LASTCHECK"; - private static final String MINISTRO_REPOSITORY_KEY="REPOSITORY"; - private static final String MINISTRO_DEFAULT_REPOSITORY="stable"; - - public static String getRepository(Context c) - { - SharedPreferences preferences=c.getSharedPreferences("Ministro", MODE_PRIVATE); - return preferences.getString(MINISTRO_REPOSITORY_KEY,MINISTRO_DEFAULT_REPOSITORY); - } - - public static void setRepository(Context c, String value) - { - SharedPreferences preferences=c.getSharedPreferences("Ministro", MODE_PRIVATE); - SharedPreferences.Editor editor= preferences.edit(); - editor.putString(MINISTRO_REPOSITORY_KEY,value); - editor.putLong(MINISTRO_CHECK_UPDATES_KEY,0); - editor.commit(); - } - - // used to check Ministro Service compatibility - private static final int MINISTRO_MIN_API_LEVEL=1; - private static final int MINISTRO_MAX_API_LEVEL=1; - - // MinistroService instance, its used by MinistroActivity to directly access services data (e.g. libraries) - private static MinistroService m_instance = null; - private String m_environmentVariables = null; - private String m_applicationParams = null; - - public static MinistroService instance() - { - return m_instance; - } - public MinistroService() { - m_instance = this; - } - - private int m_actionId=0; // last actions id - - - // current downloaded libraries - private ArrayList<Library> m_downloadedLibraries = new ArrayList<Library>(); - - ArrayList<Library> getDownloadedLibraries() - { - synchronized (this) { - return m_downloadedLibraries; - } - } - - // current available libraries - private ArrayList<Library> m_availableLibraries = new ArrayList<Library>(); - ArrayList<Library> getAvailableLibraries() - { - synchronized (this) { - return m_availableLibraries; - } - } - - class CheckForUpdates extends AsyncTask<Void, Void, Void> - { - @Override - protected void onPreExecute() { - if (m_version<MinistroActivity.downloadVersionXmlFile(MinistroService.this, true)) - { - NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - - int icon = R.drawable.icon; - CharSequence tickerText = "New Qt libs found"; // ticker-text - long when = System.currentTimeMillis(); // notification time - Context context = getApplicationContext(); // application Context - CharSequence contentTitle = "Ministro update"; // expanded message title - CharSequence contentText = "New Qt libs has been found tap to update."; // expanded message text - - Intent notificationIntent = new Intent(MinistroService.this, MinistroActivity.class); - PendingIntent contentIntent = PendingIntent.getActivity(MinistroService.this, 0, notificationIntent, 0); - - // the next two lines initialize the Notification, using the configurations above - Notification notification = new Notification(icon, tickerText, when); - notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); - notification.defaults |= Notification.DEFAULT_SOUND; - notification.defaults |= Notification.DEFAULT_VIBRATE; - notification.defaults |= Notification.DEFAULT_LIGHTS; - try{ - nm.notify(1, notification); - }catch(Exception e) - { - e.printStackTrace(); - } - } - } - - @Override - protected Void doInBackground(Void... params) { - // TODO Auto-generated method stub - return null; - } - } - - - // this method reload all downloaded libraries - synchronized ArrayList<Library> refreshLibraries(boolean checkCrc) - { - synchronized (this) { - try { - m_downloadedLibraries.clear(); - m_availableLibraries.clear(); - if (! (new File(m_versionXmlFile)).exists()) - return m_downloadedLibraries; - DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder(); - Document dom = documentBuilder.parse(new FileInputStream(m_versionXmlFile)); - Element root = dom.getDocumentElement(); - m_version = Double.valueOf(root.getAttribute("version")); - m_applicationParams=root.getAttribute("applicationParameters"); - m_applicationParams=m_applicationParams.replaceAll("MINISTRO_PATH", getFilesDir().getAbsolutePath()); - m_environmentVariables=root.getAttribute("environmentVariables"); - m_environmentVariables=m_environmentVariables.replaceAll("MINISTRO_PATH", getFilesDir().getAbsolutePath()); - root.normalize(); - Node node = root.getFirstChild(); - while(node != null) - { - if (node.getNodeType() == Node.ELEMENT_NODE) - { - Library lib= Library.getLibrary((Element)node, false); - File file=new File(m_qtLibsRootPath + lib.filePath); - if (file.exists()) - { - if (checkCrc && !Library.checkCRC(file.getAbsolutePath(), lib.sha1)) - file.delete(); - else - m_downloadedLibraries.add(lib); - } - m_availableLibraries.add(lib); - } - // Workaround for an unbelievable bug !!! - try { - node = node.getNextSibling(); - } catch (Exception e) { - e.printStackTrace(); - break; - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - return m_downloadedLibraries; - } - - // version xml file - private String m_versionXmlFile; - public String getVersionXmlFile() - { - return m_versionXmlFile; - } - - private String m_qtLibsRootPath; - public String getQtLibsRootPath() - { - return m_qtLibsRootPath; - } - - private double m_version = -1; - public double getVersion() - { - return m_version; - } - - // class used to fire an action, this class is used - // to start an activity when user needs more libraries to start its application - class ActionStruct - { - ActionStruct(IMinistroCallback cb, String[] m, ArrayList<String> notFoundMoules, String appName) - { - id=++m_actionId; - callback = cb; - modules = m; - } - public int id; - public IMinistroCallback callback; - public String[] modules; - } - - // we can have more then one action - ArrayList<ActionStruct> m_actions = new ArrayList<ActionStruct>(); - - @Override - public void onCreate() { - m_versionXmlFile = getFilesDir().getAbsolutePath()+"/version.xml"; - m_qtLibsRootPath = getFilesDir().getAbsolutePath()+"/qt/"; - SharedPreferences preferences=getSharedPreferences("Ministro", MODE_PRIVATE); - long lastCheck = preferences.getLong(MINISTRO_CHECK_UPDATES_KEY,0); - if (MinistroActivity.isOnline(this) && System.currentTimeMillis()-lastCheck>24l*3600*100) // check once/day - { - refreshLibraries(true); - SharedPreferences.Editor editor= preferences.edit(); - editor.putLong(MINISTRO_CHECK_UPDATES_KEY,System.currentTimeMillis()); - editor.commit(); - new CheckForUpdates().execute((Void[])null); - } - else - refreshLibraries(false); - super.onCreate(); - } - - @Override - public void onDestroy() { - super.onDestroy(); - } - - @Override - public IBinder onBind(Intent intent){ - return new IMinistro.Stub() { - @Override - public void checkModules(IMinistroCallback callback, - String[] modules, String appName, int ministroApiLevel, int necessitasApiLevel) throws RemoteException { - checkModulesImpl(callback, modules, appName, ministroApiLevel, necessitasApiLevel); - } - }; - } - - /** - * Implements the {@link IMinistro.Stub#checkModules(IMinistroCallback, String[], String, int, int)} - * service method. - * - * @param callback - * @param modules - * @param appName - * @param ministroApiLevel - * @param necessitasApiLevel - * @throws RemoteException - */ - final void checkModulesImpl(IMinistroCallback callback, - String[] modules, String appName, int ministroApiLevel, int necessitasApiLevel) throws RemoteException { - - if (ministroApiLevel<MINISTRO_MIN_API_LEVEL || ministroApiLevel>MINISTRO_MAX_API_LEVEL) - { - // panic !!! Ministro service is not compatible, user should upgrade Ministro package - Log.w(TAG, "Ministro cannot satisfy API version: " + ministroApiLevel); - return; - } - - // check necessitasApiLevel !!! I'm pretty sure some people will completely ignore my warning - // and they will deploying apps to Android Market, so let's try to give them a chance. - - // this method is called by the activity client who needs modules. - ArrayList<String> notFoundModules = new ArrayList<String>(); - ArrayList<String> libraries = new ArrayList<String>(); - Collections.addAll(libraries, modules); - if (checkModules(libraries, notFoundModules)) - { - // All modules are available, as such the other application can be notified that it - // can start without problems. - String[] libs = new String[libraries.size()]; - libs = libraries.toArray(libs); - callback.libs(libs, m_environmentVariables, m_applicationParams, 0, null); - } - else - { - // Starts a retrieval of the modules which are not readily accessible. - startRetrieval(callback, modules, notFoundModules, appName); - } - } - - /** - * Creates and sets up a {@link MinistroActivity} to retrieve the modules specified in the - * <code>notFoundModules</code> argument. - * - * @param callback - * @param modules - * @param notFoundModules - * @param appName - * @throws RemoteException - */ - private void startRetrieval(IMinistroCallback callback, - String[] modules, ArrayList<String> notFoundModules, String appName) - throws RemoteException - { - ActionStruct as = new ActionStruct(callback, modules, notFoundModules, appName); - m_actions.add(as); // if not, lets start an activity to do it. - - Intent intent = new Intent(MinistroService.this, MinistroActivity.class); - intent.putExtra("id", as.id); - String[] libs = notFoundModules.toArray(new String[notFoundModules.size()]); - intent.putExtra("modules", libs); - intent.putExtra("name", appName); - - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - boolean failed = false; - try - { - MinistroService.this.startActivity(intent); - } - catch(Exception e) - { - failed = true; - throw (RemoteException) new RemoteException().initCause(e); - } - finally - { - // Removes the dead Activity from our list as it will never finish by itself. - if (failed) - m_actions.remove(as); - } - } - - /** - * Called by a finished {@link MinistroActivity} in order to let - * the service notify the application which caused the activity about - * the result of the retrieval. - * - * @param id - */ - void retrievalFinished(int id) - { - for (int i=0;i<m_actions.size();i++) - { - ActionStruct action=m_actions.get(i); - if (action.id==id) - { - postRetrieval(action.callback, action.modules); - - m_actions.remove(i); - break; - } - } - if (m_actions.size() == 0) - m_actionId = 0; - } - - /** - * Helper method for the last step of the retrieval process. - * - * <p>Checks the availability of the requested modules and informs - * the requesting application about it via the {@link IMinistroCallback} - * instance.</p> - * - * @param callback - * @param modules - */ - private void postRetrieval(IMinistroCallback callback, String[] modules) { - ArrayList<String> libraries = new ArrayList<String>(); - Collections.addAll(libraries, modules); - - // Does a final check whether the libraries are accessible (without caring for - // the non-accessible ones). - boolean res = checkModules(libraries, null); - - String[] libs = new String[libraries.size()]; - libs = libraries.toArray(libs); - - try - { - if (res) - callback.libs(libs, m_environmentVariables, m_applicationParams ,0, null); - else - callback.libs(libs, m_environmentVariables, m_applicationParams, 1, "Can't find all modules"); - } - catch (RemoteException e) - { - Log.w(TAG, "Was unable to do 'libs' callback after retrieving libraries. Ignoring and assuming that the other application exited."); - } - - } - - /** - * Checks whether a given list of libraries are readily accessible (e.g. usable by a program). - * - * <p>If the <code>notFoundModules</code> argument is given, the method fills the list with - * libraries that need to be retrieved first.</p> - * - * @param libs - * @param notFoundModules - * @return - */ - boolean checkModules(ArrayList<String> libs, ArrayList<String> notFoundModules) - { - ArrayList<Module> modules= new ArrayList<Module>(); - boolean res=true; - for (int i=0;i<libs.size();i++) - res = res & addModules(libs.get(i), modules, notFoundModules); // don't stop on first error - - // sort all libraries - Collections.sort(modules, new ModuleCompare()); - libs.clear(); - for (int i=0;i<modules.size();i++) - libs.add(m_qtLibsRootPath+modules.get(i).path); - return res; - } - - /** - * Helper method for the module resolution mechanism. It deals with an individual module's - * resolution request. - * - * <p>The method checks whether a given <em>single</em> <code>module</code> is already - * accessible or needs to be retrieved first. In the latter case the method returns - * <code>false</code>.</p> - * - * <p>The method traverses a <code>module<code>'s dependencies automatically.</p> - * - * <p>In order to find out whether a <code>module</code> is accessible the method consults - * the list of downloaded libraries. If found, an entry to the <code>modules</code> list is - * added.</p> - * - * <p>In case the <code>module</ocde> is not immediately accessible and the <code>notFoundModules</code> - * argument exists, a list of available libraries is consulted to fill a list of modules which - * yet need to be retrieved.</p> - * - * @param module - * @param modules - * @param notFoundModules - * @return <code>true</code> if the given module and all its dependencies are readily available. - */ - private boolean addModules(String module, ArrayList<Module> modules, ArrayList<String> notFoundModules) - { - // Module argument is not supposed to be null at this point. - if (modules == null) - return false; // we are in deep shit if this happens - - // Short-cut: If the module is already in our list of previously found modules then we do not - // need to consult the list of downloaded modules. - for (int i=0;i<modules.size();i++) - { - if (modules.get(i).name.equals(module)) - return true; - } - - // Consult the list of downloaded modules. If a matching entry is found, it is added to the - // list of readily accessible modules and its dependencies are checked via a recursive call. - for (int i = 0; i< m_downloadedLibraries.size(); i++) - { - if (m_downloadedLibraries.get(i).name.equals(module)) - { - Module m = new Module(); - m.name=m_downloadedLibraries.get(i).name; - m.path=m_downloadedLibraries.get(i).filePath; - m.level=m_downloadedLibraries.get(i).level; - modules.add(m); - boolean res = true; - if (m_downloadedLibraries.get(i).depends != null) - for (int depIt=0;depIt<m_downloadedLibraries.get(i).depends.length;depIt++) - res &= addModules(m_downloadedLibraries.get(i).depends[depIt], modules, notFoundModules); - return res; - } - } - - // Requested module is not readily accessible. - if (notFoundModules != null) - { - // Checks list of modules which are known to not be readily accessible and returns early to - // prevent double entries. - for (int i=0;i<notFoundModules.size();i++) - { - if (notFoundModules.get(i).equals(module)) - return false; - } - - // Deal with not yet readily accessible module's dependencies. - notFoundModules.add(module); - for (int i = 0; i< m_availableLibraries.size(); i++) - { - if (m_availableLibraries.get(i).name.equals(module)) - { - if (m_availableLibraries.get(i).depends != null) - for (int depIt=0;depIt<m_availableLibraries.get(i).depends.length;depIt++) - addModules(m_availableLibraries.get(i).depends[depIt], modules, notFoundModules); - break; - } - } - } - return false; - } - -/** Sorter for libraries. - * - * Hence the order in which the libraries have to be loaded is important, it is neccessary - * to sort them. - */ -static private class ModuleCompare implements Comparator<Module> { - @Override - public int compare(Module a, Module b) { - return a.level-b.level; - } -} - -/** Helper class which allows manipulating libraries. - * - * It is similar to the {@link Library} class but has fewer fields. - */ -static private class Module -{ - String path; - String name; - int level; - -} - -}
\ No newline at end of file |