1
0
mirror of https://github.com/etesync/android synced 2024-11-15 20:38:58 +00:00

Refactoring

* make DavResourceFinder.Configuration really serializable
This commit is contained in:
Ricki Hirner 2016-02-24 12:29:07 +01:00
parent 6ac5fe0204
commit 50f7006e59
9 changed files with 108 additions and 120 deletions

View File

@ -10,15 +10,15 @@ package at.bitfire.davdroid.model;
import android.content.ContentValues;
public class DavService {
public class Service {
public long id;
public String accountName, service, principal;
public long lastRefresh;
public static DavService fromDB(ContentValues values) {
DavService service = new DavService();
public static Service fromDB(ContentValues values) {
Service service = new Service();
service.id = values.getAsLong(ServiceDB.Services.ID);
service.accountName = values.getAsString(ServiceDB.Services.ACCOUNT_NAME);
service.service = values.getAsString(ServiceDB.Services.SERVICE);

View File

@ -222,7 +222,7 @@ abstract public class SyncManager {
final Intent detailsIntent;
if (e instanceof UnauthorizedException) {
detailsIntent = new Intent(context, AccountActivity.class);
detailsIntent.putExtra(AccountActivity.EXTRA_ACCOUNT_NAME, account.name);
detailsIntent.putExtra(AccountActivity.EXTRA_ACCOUNT, account);
} else {
detailsIntent = new Intent(context, DebugInfoActivity.class);
detailsIntent.putExtra(DebugInfoActivity.KEY_EXCEPTION, e);

View File

@ -35,13 +35,11 @@ import android.os.IBinder;
import android.provider.CalendarContract;
import android.provider.ContactsContract;
import android.support.design.widget.Snackbar;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.AppCompatRadioButton;
import android.support.v7.widget.CardView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@ -55,7 +53,6 @@ import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.commons.lang3.BooleanUtils;
@ -74,8 +71,7 @@ import at.bitfire.ical4android.TaskProvider;
import lombok.Cleanup;
public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenuItemClickListener, PopupMenu.OnMenuItemClickListener, LoaderManager.LoaderCallbacks<AccountActivity.AccountInfo> {
public static final String EXTRA_ACCOUNT_NAME = "account_name";
public static final String EXTRA_ACCOUNT = "account";
private Account account;
private AccountInfo accountInfo;
@ -87,12 +83,8 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String accountName = getIntent().getStringExtra(EXTRA_ACCOUNT_NAME);
if (accountName == null)
// invalid account name
finish();
setTitle(accountName);
account = new Account(accountName, Constants.ACCOUNT_TYPE);
account = getIntent().getParcelableExtra(EXTRA_ACCOUNT);
setTitle(account.name);
setContentView(R.layout.activity_account);
@ -183,19 +175,6 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
}
/* LOADERS AND LOADED DATA */
protected static class AccountInfo {
ServiceInfo carddav, caldav;
public static class ServiceInfo {
long id;
boolean refreshing;
List<CollectionInfo> collections;
}
}
private AdapterView.OnItemClickListener onItemClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
@ -264,9 +243,23 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
}
};
/* LOADERS AND LOADED DATA */
protected static class AccountInfo {
ServiceInfo carddav, caldav;
public static class ServiceInfo {
long id;
boolean refreshing;
List<CollectionInfo> collections;
}
}
@Override
public Loader<AccountInfo> onCreateLoader(int id, Bundle args) {
return new AccountLoader(this, args.getString(EXTRA_ACCOUNT_NAME));
return new AccountLoader(this, account.name);
}
public void reload() {
@ -314,6 +307,8 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
@Override
public void onLoaderReset(Loader<AccountInfo> loader) {
listCardDAV.setAdapter(null);
listCalDAV.setAdapter(null);
}

View File

@ -23,13 +23,10 @@ import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.util.LinkedList;
@ -37,7 +34,6 @@ import java.util.List;
import at.bitfire.davdroid.AccountsChangedReceiver;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.DavService;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.model.ServiceDB.OpenHelper;
import at.bitfire.davdroid.model.ServiceDB.Services;
@ -68,11 +64,19 @@ public class AccountListFragment extends ListFragment implements LoaderManager.L
AccountInfo info = (AccountInfo)getListAdapter().getItem(position);
Intent intent = new Intent(getContext(), AccountActivity.class);
intent.putExtra(AccountActivity.EXTRA_ACCOUNT_NAME, info.account.name);
intent.putExtra(AccountActivity.EXTRA_ACCOUNT, info.account);
startActivity(intent);
}
// loader
@RequiredArgsConstructor
protected static class AccountInfo {
final Account account;
Long cardDavService, calDavService;
}
@Override
public Loader<List<AccountInfo>> onCreateLoader(int id, Bundle args) {
return new AccountLoader(getContext());
@ -87,37 +91,7 @@ public class AccountListFragment extends ListFragment implements LoaderManager.L
@Override
public void onLoaderReset(Loader<List<AccountInfo>> loader) {
}
@RequiredArgsConstructor
protected static class AccountInfo {
final Account account;
Long cardDavService, calDavService;
}
static class AccountListAdapter extends ArrayAdapter<AccountInfo> {
public AccountListAdapter(Context context) {
super(context, R.layout.account_list_item);
}
@Override
public View getView(int position, View v, ViewGroup parent) {
if (v == null)
v = LayoutInflater.from(getContext()).inflate(R.layout.account_list_item, parent, false);
AccountInfo info = getItem(position);
TextView tv = (TextView)v.findViewById(R.id.account_name);
tv.setText(info.account.name);
tv = (TextView)v.findViewById(R.id.carddav);
tv.setVisibility(info.cardDavService != null ? View.VISIBLE : View.GONE);
tv = (TextView)v.findViewById(R.id.caldav);
tv.setVisibility(info.calDavService != null ? View.VISIBLE : View.GONE);
return v;
}
((AccountListAdapter)getListAdapter()).clear();
}
private static class AccountLoader extends AsyncTaskLoader<List<AccountInfo>> implements OnAccountsUpdateListener {
@ -177,7 +151,33 @@ public class AccountListFragment extends ListFragment implements LoaderManager.L
}
return accounts;
}
}
// list adapter
static class AccountListAdapter extends ArrayAdapter<AccountInfo> {
public AccountListAdapter(Context context) {
super(context, R.layout.account_list_item);
}
@Override
public View getView(int position, View v, ViewGroup parent) {
if (v == null)
v = LayoutInflater.from(getContext()).inflate(R.layout.account_list_item, parent, false);
AccountInfo info = getItem(position);
TextView tv = (TextView)v.findViewById(R.id.account_name);
tv.setText(info.account.name);
tv = (TextView)v.findViewById(R.id.carddav);
tv.setVisibility(info.cardDavService != null ? View.VISIBLE : View.GONE);
tv = (TextView)v.findViewById(R.id.caldav);
tv.setVisibility(info.calDavService != null ? View.VISIBLE : View.GONE);
return v;
}
}
}

View File

@ -42,11 +42,11 @@ public class AccountSettingsActivity extends AppCompatActivity {
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
Intent intent = new Intent(this, AccountActivity.class);
intent.putExtra(AccountActivity.EXTRA_ACCOUNT_NAME, account.name);
intent.putExtra(AccountActivity.EXTRA_ACCOUNT, account);
NavUtils.navigateUpTo(this, intent);
return true;
} else
return super.onOptionsItemSelected(item);
return false;
}
}

View File

@ -47,7 +47,7 @@ import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.HttpClient;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.model.CollectionInfo;
import at.bitfire.davdroid.model.DavService;
import at.bitfire.davdroid.model.Service;
import at.bitfire.davdroid.model.HomeSet;
import at.bitfire.davdroid.model.ServiceDB;
import at.bitfire.davdroid.syncadapter.AccountSettings;
@ -82,7 +82,7 @@ public class CreateAddressBookActivity extends AppCompatActivity implements Load
switch (item.getItemId()) {
case android.R.id.home:
Intent intent = new Intent(this, AccountActivity.class);
intent.putExtra(AccountActivity.EXTRA_ACCOUNT_NAME, account.name);
intent.putExtra(AccountActivity.EXTRA_ACCOUNT, account);
NavUtils.navigateUpTo(this, intent);
break;
case R.id.create_address_book:
@ -280,7 +280,7 @@ public class CreateAddressBookActivity extends AppCompatActivity implements Load
}
protected static class AccountInfo {
DavService service;
Service service;
List<HomeSet> homeSets = new LinkedList<>();
}
@ -312,7 +312,7 @@ public class CreateAddressBookActivity extends AppCompatActivity implements Load
ContentValues values = new ContentValues();
DatabaseUtils.cursorRowToContentValues(cursorService, values);
info.service = DavService.fromDB(values);
info.service = Service.fromDB(values);
@Cleanup Cursor cursorHomeSets = db.query(ServiceDB.HomeSets._TABLE, null, ServiceDB.HomeSets.SERVICE_ID + "=?",
new String[] { String.valueOf(info.service.id) }, null, null, null);

View File

@ -102,7 +102,7 @@ public class CreateCalendarActivity extends AppCompatActivity implements LoaderM
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
Intent intent = new Intent(this, AccountActivity.class);
intent.putExtra(AccountActivity.EXTRA_ACCOUNT_NAME, account.name);
intent.putExtra(AccountActivity.EXTRA_ACCOUNT, account);
NavUtils.navigateUpTo(this, intent);
return true;
}

View File

@ -25,29 +25,30 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import java.util.Map;
import java.net.URI;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.DavService;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.model.CollectionInfo;
import at.bitfire.davdroid.model.ServiceDB.Collections;
import at.bitfire.davdroid.model.ServiceDB.HomeSets;
import at.bitfire.davdroid.model.ServiceDB.OpenHelper;
import at.bitfire.davdroid.model.ServiceDB.Services;
import at.bitfire.davdroid.syncadapter.AccountSettings;
import at.bitfire.davdroid.model.ServiceDB.*;
import at.bitfire.ical4android.TaskProvider;
import lombok.Cleanup;
import okhttp3.HttpUrl;
public class AccountDetailsFragment extends Fragment {
private static final String KEY_CONFIG = "config";
public static AccountDetailsFragment newInstance(DavResourceFinder.Configuration config) {
AccountDetailsFragment frag = new AccountDetailsFragment();
Bundle args = new Bundle(1);
args.putSerializable(KEY_CONFIG, config);
AccountDetailsFragment fragment = new AccountDetailsFragment();
fragment.setArguments(args);
return fragment;
frag.setArguments(args);
return frag;
}
@Override
@ -145,12 +146,12 @@ public class AccountDetailsFragment extends Fragment {
// insert service
values.put(Services.ACCOUNT_NAME, accountName);
values.put(Services.SERVICE, service);
if (info.getPrincipal() != null)
values.put(Services.PRINCIPAL, info.getPrincipal().toString());
if (info.principal != null)
values.put(Services.PRINCIPAL, info.principal.toString());
long serviceID = db.insertOrThrow(Services._TABLE, null, values);
// insert home sets
for (HttpUrl homeSet : info.getHomeSets()) {
for (URI homeSet : info.homeSets) {
values.clear();
values.put(HomeSets.SERVICE_ID, serviceID);
values.put(HomeSets.URL, homeSet.toString());
@ -158,7 +159,7 @@ public class AccountDetailsFragment extends Fragment {
}
// insert collections
for (CollectionInfo collection : info.getCollections().values()) {
for (CollectionInfo collection : info.collections.values()) {
values = collection.toDB();
values.put(Collections.SERVICE_ID, serviceID);
db.insertOrThrow(Collections._TABLE, null, values);

View File

@ -46,9 +46,7 @@ import at.bitfire.dav4android.property.SupportedCalendarComponentSet;
import at.bitfire.davdroid.HttpClient;
import at.bitfire.davdroid.log.StringLogger;
import at.bitfire.davdroid.model.CollectionInfo;
import lombok.Data;
import lombok.Getter;
import android.support.annotation.NonNull;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import okhttp3.HttpUrl;
@ -181,7 +179,7 @@ public class DavResourceFinder {
// If a principal has been detected successfully, ensure that it provides the required service.
if (principal != null && providesService(principal, service))
config.principal = principal;
config.principal = principal.uri();
} catch (IOException|HttpException|DavException e) {
log.debug("PROPFIND/OPTIONS on user-given URL failed", e);
@ -194,14 +192,14 @@ public class DavResourceFinder {
if (resourceType != null && resourceType.types.contains(ResourceType.ADDRESSBOOK)) {
dav.location = UrlUtils.withTrailingSlash(dav.location);
log.info("Found address book at " + dav.location);
config.collections.put(dav.location, CollectionInfo.fromDavResource(dav));
config.collections.put(dav.location.uri(), CollectionInfo.fromDavResource(dav));
}
// Does the collection refer to address book homesets?
AddressbookHomeSet homeSets = (AddressbookHomeSet)dav.properties.get(AddressbookHomeSet.NAME);
if (homeSets != null)
for (String href : homeSets.hrefs)
config.homeSets.add(UrlUtils.withTrailingSlash(dav.location.resolve(href)));
config.homeSets.add(UrlUtils.withTrailingSlash(dav.location.resolve(href)).uri());
}
protected void rememberIfCalendarOrHomeset(@NonNull DavResource dav, @NonNull Configuration.ServiceInfo config) {
@ -210,14 +208,14 @@ public class DavResourceFinder {
if (resourceType != null && resourceType.types.contains(ResourceType.CALENDAR)) {
dav.location = UrlUtils.withTrailingSlash(dav.location);
log.info("Found calendar collection at " + dav.location);
config.collections.put(dav.location, CollectionInfo.fromDavResource(dav));
config.collections.put(dav.location.uri(), CollectionInfo.fromDavResource(dav));
}
// Does the collection refer to calendar homesets?
CalendarHomeSet homeSets = (CalendarHomeSet)dav.properties.get(CalendarHomeSet.NAME);
if (homeSets != null)
for (String href : homeSets.hrefs)
config.homeSets.add(UrlUtils.withTrailingSlash(dav.location.resolve(href)));
config.homeSets.add(UrlUtils.withTrailingSlash(dav.location.resolve(href)).uri());
}
@ -244,9 +242,9 @@ public class DavResourceFinder {
* @param service service to discover (CALDAV or CARDDAV)
* @return principal URL, or null if none found
*/
protected HttpUrl discoverPrincipalUrl(String domain, Service service) throws IOException, HttpException, DavException {
String scheme = null;
String fqdn = null;
protected URI discoverPrincipalUrl(@NonNull String domain, @NonNull Service service) throws IOException, HttpException, DavException {
String scheme;
String fqdn;
Integer port = 443;
List<String> paths = new LinkedList<>(); // there may be multiple paths to try
@ -275,7 +273,7 @@ public class DavResourceFinder {
if (records != null)
for (Record record : records)
if (record instanceof TXTRecord)
for (String segment : (List<String>) ((TXTRecord) record).getStrings())
for (String segment : (List<String>)((TXTRecord)record).getStrings())
if (segment.startsWith("path=")) {
paths.add(segment.substring(5));
log.info("Found TXT record; initial context path=" + paths);
@ -289,19 +287,17 @@ public class DavResourceFinder {
for (String path : paths)
try {
if (!TextUtils.isEmpty(scheme) && !TextUtils.isEmpty(fqdn) && paths != null) {
HttpUrl initialContextPath = new HttpUrl.Builder()
.scheme(scheme)
.host(fqdn).port(port)
.encodedPath(path)
.build();
HttpUrl initialContextPath = new HttpUrl.Builder()
.scheme(scheme)
.host(fqdn).port(port)
.encodedPath(path)
.build();
log.info("Trying to determine principal from initial context path=" + initialContextPath);
HttpUrl principal = getCurrentUserPrincipal(initialContextPath, service);
log.info("Trying to determine principal from initial context path=" + initialContextPath);
URI principal = getCurrentUserPrincipal(initialContextPath, service);
if (principal != null)
return principal;
}
if (principal != null)
return principal;
} catch(NotFoundException e) {
log.warn("No resource found", e);
}
@ -314,7 +310,7 @@ public class DavResourceFinder {
* @param service required service (may be null, in which case no service check is done)
* @return current-user-principal URL that provides required service, or null if none
*/
public HttpUrl getCurrentUserPrincipal(HttpUrl url, Service service) throws IOException, HttpException, DavException {
public URI getCurrentUserPrincipal(HttpUrl url, Service service) throws IOException, HttpException, DavException {
DavResource dav = new DavResource(log, httpClient, url);
dav.propfind(0, CurrentUserPrincipal.NAME);
CurrentUserPrincipal currentUserPrincipal = (CurrentUserPrincipal) dav.properties.get(CurrentUserPrincipal.NAME);
@ -329,7 +325,7 @@ public class DavResourceFinder {
principal = null;
}
return principal;
return principal != null ? principal.uri() : null;
}
}
return null;
@ -350,6 +346,14 @@ public class DavResourceFinder {
@RequiredArgsConstructor
@ToString(exclude="logs")
public static class Configuration implements Serializable {
// We have to use URI here because HttpUrl is not serializable!
@ToString
public static class ServiceInfo implements Serializable {
public URI principal;
public final Set<URI> homeSets = new HashSet<>();
public final Map<URI, CollectionInfo> collections = new HashMap<>();
}
public final String userName, password;
public final boolean preemptive;
@ -359,18 +363,6 @@ public class DavResourceFinder {
public final String logs;
@ToString
public static class ServiceInfo implements Serializable {
@Getter
HttpUrl principal;
@Getter
final Set<HttpUrl> homeSets = new HashSet<>();
@Getter
final Map<HttpUrl, CollectionInfo> collections = new HashMap<>();
}
}
}