package com.ghostsq.commander.adapters;
import java.io.File;
import java.lang.reflect.Constructor;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Environment;
import android.util.Log;
import com.ghostsq.commander.Commander;
import com.ghostsq.commander.Dialogs;
import com.ghostsq.commander.R;
import com.ghostsq.commander.root.MountAdapter;
import com.ghostsq.commander.root.RootAdapter;
import dalvik.system.DexClassLoader;
/**
* <code>CA</code> class
* @author Ghost Squared (ghost.sq2@gmail.com)
*
* This class is a "database" of all implemented adapters.
* It keeps all the properties, hashes etc, to let the right adapter be instatiated
*
*/
final public class CA {
public static final String TAG = "CA";
public static final int FS = 0x00000001;
public static final int FIND = 0x00000002;
public static final int LOCAL = FS | FIND;
public static final int HOME = 0x00000010;
public static final int FAVS = 0x00000020;
public static final int NAV = FAVS | HOME;
public static final int ZIP = 0x00000100;
public static final int ARCH = ZIP;
public static final int ROOT = 0x00001000;
public static final int MNT = 0x00002000;
public static final int APPS = 0x00004000;
public static final int FTP = 0x00010000;
public static final int SMB = 0x00020000;
public static final int DBOX = 0x00040000;
public static final int GDOCS = 0x00080000;
public static final int SFTP = 0x00100000;
public static final int BOX = 0x00200000;
public static final int NET = FTP | SMB | GDOCS | SFTP | BOX;
public static final int REAL = LOCAL | ARCH | ROOT | NET;
public static final int CHKBL = REAL | APPS | FAVS;
public static final int ALL = 0xFFFFFFFF;
// URI schemes hash codes
protected static final int home_schema_h = "home".hashCode();
protected static final int zip_schema_h = "zip".hashCode();
protected static final int ftp_schema_h = "ftp".hashCode();
protected static final int sftp_schema_h = "sftp".hashCode();
protected static final int find_schema_h = "find".hashCode();
protected static final int root_schema_h = "root".hashCode();
protected static final int mnt_schema_h = "mount".hashCode();
protected static final int apps_schema_h = "apps".hashCode();
protected static final int favs_schema_h = "favs".hashCode();
protected static final int smb_schema_h = "smb".hashCode();
protected static final int dbox_schema_h = "dbox".hashCode();
protected static final int box_schema_h = "box".hashCode();
protected static final int gd_schema_h = "gd".hashCode();
protected static final int gdocs_schema_h = "gdocs".hashCode();
/**
the mapping between the scheme and the adapter type id
("many-one" - because we could let the user to enter short aliases for the scheme instead)
*/
public final static int GetAdapterTypeId( String scheme ) {
if( scheme == null || scheme.length() == 0 ) return FS;
final int scheme_h = scheme.hashCode();
if( home_schema_h == scheme_h ) return HOME;
if( zip_schema_h == scheme_h ) return ZIP;
if( ftp_schema_h == scheme_h ) return FTP;
if( sftp_schema_h == scheme_h ) return SFTP;
if( find_schema_h == scheme_h ) return FIND;
if( root_schema_h == scheme_h ) return ROOT;
if( mnt_schema_h == scheme_h ) return MNT;
if( apps_schema_h == scheme_h ) return APPS;
if( favs_schema_h == scheme_h ) return FAVS;
if( smb_schema_h == scheme_h ) return SMB;
if( dbox_schema_h == scheme_h ) return DBOX;
if( box_schema_h == scheme_h ) return BOX;
if( gd_schema_h == scheme_h ) return GDOCS;
if(gdocs_schema_h == scheme_h ) return GDOCS;
return FS;
}
public final static boolean isLocal( String scheme ) {
return scheme == null || scheme.length() == 0 || "file".equals( scheme ) || "find".equals( scheme );
}
public final static CommanderAdapter CreateAdapter( int type_id, Commander c ) {
CommanderAdapter ca = CreateAdapterInstance( type_id, c.getContext() );
if( ca != null )
ca.Init( c );
else {
if( type_id == SMB )
c.showDialog( Dialogs.SMB_PLG_DIALOG );
if( type_id == SFTP )
c.showDialog( Dialogs.SFTP_PLG_DIALOG );
}
return ca;
}
public final static CommanderAdapter CreateAdapterInstance( int type_id, Context c ) {
CommanderAdapter ca;
if( type_id == FS ) ca = new FSAdapter( c ); else
if( type_id == HOME ) ca = new HomeAdapter( c ); else
if( type_id == ZIP ) ca = new ZipAdapter( c ); else
if( type_id == FTP ) ca = new FTPAdapter( c ); else
if( type_id == FIND ) ca = new FindAdapter( c ); else
if( type_id == ROOT ) ca = new RootAdapter( c ); else
if( type_id == MNT ) ca = new MountAdapter( c ); else
if( type_id == APPS ) ca = new AppsAdapter( c ); else
if( type_id == FAVS ) ca = new FavsAdapter( c ); else
if( type_id == SMB ) ca = CreateExternalAdapter( c, "samba", "SMBAdapter" ); else
if( type_id == DBOX ) ca = CreateExternalAdapter( c, "dropbox","DBoxAdapter" ); else
if( type_id == BOX ) ca = CreateExternalAdapter( c, "box", "BoxAdapter" ); else
if( type_id == SFTP ) ca = CreateExternalAdapter( c, "sftp", "SFTPAdapter" ); else
ca = null;
return ca;
}
/**
* CreateExternalAdapter Tries to load an adapter class from foreign package
* @param String type - adapter type, also the suffix of the plugin application
* @param String class_name - the adapter class name to be loaded
* @param int dialog_id - resource ID to show dialog if the class can't be loaded
*/
public static CommanderAdapter CreateExternalAdapter( Context ctx, String type, String class_name ) {
try {
File dex_f = ctx.getDir( type, Context.MODE_PRIVATE );
if( dex_f == null || !dex_f.exists() ) {
Log.w( TAG, "app.data storage is not accessable, trying to use the SD card" );
File sd = Environment.getExternalStorageDirectory();
if( sd == null ) return null; // nowhere to store the dex :(
dex_f = new File( sd, "temp" );
if( !dex_f.exists() )
dex_f.mkdir();
}
ApplicationInfo ai = ctx.getPackageManager().getApplicationInfo( "com.ghostsq.commander." + type, 0 );
Log.i( TAG, type + " package is " + ai.sourceDir );
ClassLoader pcl = ctx.getClass().getClassLoader();
DexClassLoader cl = new DexClassLoader( ai.sourceDir, dex_f.getAbsolutePath(), null, pcl );
//
Class<?> adapterClass = cl.loadClass( "com.ghostsq.commander." + type + "." + class_name );
Log.i( TAG, "Class has been loaded " + adapterClass.toString() );
try {
File[] list = dex_f.listFiles();
for( int i = 0; i < list.length; i++ )
list[i].delete();
}
catch( Exception e ) {
Log.w( TAG, "Can't remove the plugin's .dex: ", e );
}
if( adapterClass != null ) {
Constructor<?> constr = null;
try {
constr = adapterClass.getConstructor( Context.class );
} catch( Exception e ) {
e.printStackTrace();
}
if( constr != null )
return (CommanderAdapter)constr.newInstance( ctx );
else
return (CommanderAdapter)adapterClass.newInstance();
}
}
catch( Throwable e ) {
Log.e( TAG, "This class can't be created: " + type, e );
}
return null;
}
public final static int getSuitableAdapter( int cmd_id ) {
switch( cmd_id ) {
case R.id.F1: return CA.ALL;
case R.id.F2: return CA.REAL | CA.FAVS;
case R.id.F3: return CA.REAL;
case R.id.F4: return CA.REAL & ~CA.ARCH | CA.FAVS;
case R.id.SF4: return CA.FS;
case R.id.F5: return CA.REAL | CA.APPS;
case R.id.F6: return CA.REAL;
case R.id.F7: return CA.REAL & ~CA.FIND | CA.MNT;
case R.id.F8: return CA.REAL | CA.FAVS | CA.APPS;
case R.id.F9: return CA.ALL;
case R.id.F10: return CA.ALL;
case R.id.eq: return CA.ALL;
case R.id.tgl: return CA.ALL;
case R.id.sz: return CA.LOCAL | CA.ROOT | CA.APPS | CA.SMB | CA.SFTP;
case R.id.by_name: return CA.REAL | CA.APPS | CA.FAVS;
case R.id.by_ext: return CA.REAL | CA.APPS | CA.FAVS;
case R.id.by_size: return CA.REAL | CA.APPS | CA.FAVS;
case R.id.by_date: return CA.REAL | CA.APPS;
case R.id.sel_all: return CA.REAL | CA.APPS;
case R.id.uns_all: return CA.REAL | CA.APPS;
case R.id.enter: return CA.ALL;
case R.id.add_fav: return CA.ALL;
case R.id.remount: return CA.ROOT;
case R.id.home: return CA.ALL & ~CA.HOME;
case R.id.favs: return CA.ALL & ~CA.FAVS;
case R.id.sdcard: return CA.ALL;
case R.id.root: return CA.ALL;
case R.id.mount: return CA.ROOT | CA.NAV;
case R.id.hidden: return CA.REAL;
case R.id.refresh: return CA.REAL | CA.FAVS;
case R.id.softkbd: return CA.ALL;
case R.id.search: return CA.LOCAL;
case R.id.menu: return CA.ALL;
}
return 0;
}
public final static boolean suitable( int cmd_id, int type ) {
int sa_type = getSuitableAdapter( cmd_id );
return ( sa_type & type ) != 0;
}
}