Merge pull request #64 from sismics/master

Push to production
This commit is contained in:
Benjamin Gamard 2016-02-11 23:41:47 +01:00
commit 3248637e8c
52 changed files with 1075 additions and 1472 deletions

View File

@ -89,11 +89,11 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtimfe-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
@ -108,18 +108,16 @@
<orderEntry type="library" exported="" name="support-annotations-23.1.1" level="project" /> <orderEntry type="library" exported="" name="support-annotations-23.1.1" level="project" />
<orderEntry type="library" exported="" name="android-easing-1.0.3" level="project" /> <orderEntry type="library" exported="" name="android-easing-1.0.3" level="project" />
<orderEntry type="library" exported="" name="imagezoom-1.0.5" level="project" /> <orderEntry type="library" exported="" name="imagezoom-1.0.5" level="project" />
<orderEntry type="library" exported="" name="android-async-http-1.4.9" level="project" /> <orderEntry type="library" exported="" name="okhttp-urlconnection-3.1.1" level="project" />
<orderEntry type="library" exported="" name="picasso-2.5.2" level="project" /> <orderEntry type="library" exported="" name="picasso-2.5.2" level="project" />
<orderEntry type="library" exported="" name="eventbus-2.4.1" level="project" />
<orderEntry type="library" exported="" name="recyclerview-v7-23.1.1" level="project" /> <orderEntry type="library" exported="" name="recyclerview-v7-23.1.1" level="project" />
<orderEntry type="library" exported="" name="okhttp-urlconnection-3.0.1" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.1.1" level="project" /> <orderEntry type="library" exported="" name="support-v4-23.1.1" level="project" />
<orderEntry type="library" exported="" name="fab-0.0.6" level="project" /> <orderEntry type="library" exported="" name="fab-0.0.6" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-23.1.1" level="project" /> <orderEntry type="library" exported="" name="appcompat-v7-23.1.1" level="project" />
<orderEntry type="library" exported="" name="httpclient-4.3.6" level="project" /> <orderEntry type="library" exported="" name="okhttp-3.1.1" level="project" />
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" /> <orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
<orderEntry type="library" exported="" name="picasso2-okhttp3-downloader-1.0.2" level="project" /> <orderEntry type="library" exported="" name="picasso2-okhttp3-downloader-1.0.2" level="project" />
<orderEntry type="library" exported="" name="tokenautocomplete-1.2.1" level="project" /> <orderEntry type="library" exported="" name="tokenautocomplete-1.2.1" level="project" />
<orderEntry type="library" exported="" name="okhttp-3.0.1" level="project" /> <orderEntry type="library" exported="" name="eventbus-3.0.0" level="project" />
</component> </component>
</module> </module>

View File

@ -3,7 +3,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.0.0-alpha7' classpath 'com.android.tools.build:gradle:2.0.0-beta3'
} }
} }
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
@ -52,12 +52,11 @@ dependencies {
compile fileTree(dir: 'libs', include: '*.jar') compile fileTree(dir: 'libs', include: '*.jar')
compile 'com.android.support:appcompat-v7:23.1.1' compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1' compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'com.loopj.android:android-async-http:1.4.9'
compile 'it.sephiroth.android.library.imagezoom:imagezoom:1.0.5' compile 'it.sephiroth.android.library.imagezoom:imagezoom:1.0.5'
compile 'de.greenrobot:eventbus:2.4.1' compile 'org.greenrobot:eventbus:3.0.0'
compile 'com.shamanland:fab:0.0.6' compile 'com.shamanland:fab:0.0.6'
compile 'com.squareup.picasso:picasso:2.5.2' compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.squareup.okhttp3:okhttp:3.0.1' compile 'com.squareup.okhttp3:okhttp:3.1.1'
compile "com.squareup.okhttp3:okhttp-urlconnection:3.0.1" compile "com.squareup.okhttp3:okhttp-urlconnection:3.1.1"
compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.0.2' compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.0.2'
} }

View File

@ -1,7 +1,6 @@
package com.sismics.docs.activity; package com.sismics.docs.activity;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.util.Log; import android.util.Log;
@ -25,6 +24,7 @@ import com.sismics.docs.ui.view.DatePickerView;
import com.sismics.docs.ui.view.TagsCompleteTextView; import com.sismics.docs.ui.view.TagsCompleteTextView;
import com.sismics.docs.util.PreferenceUtil; import com.sismics.docs.util.PreferenceUtil;
import org.greenrobot.eventbus.EventBus;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -35,8 +35,6 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import de.greenrobot.event.EventBus;
/** /**
* Document edition activity. * Document edition activity.
* *
@ -123,7 +121,7 @@ public class DocumentEditActivity extends AppCompatActivity {
} else { } else {
setTitle(R.string.edit_document); setTitle(R.string.edit_document);
titleEditText.setText(document.optString("title")); titleEditText.setText(document.optString("title"));
descriptionEditText.setText(document.optString("description")); descriptionEditText.setText(document.isNull("description") ? "" : document.optString("description"));
datePickerView.setDate(new Date(document.optLong("create_date"))); datePickerView.setDate(new Date(document.optLong("create_date")));
languageSpinner.setSelection(languageAdapter.getItemPosition(document.optString("language"))); languageSpinner.setSelection(languageAdapter.getItemPosition(document.optString("language")));
JSONArray documentTags = document.optJSONArray("tags"); JSONArray documentTags = document.optJSONArray("tags");
@ -164,13 +162,7 @@ public class DocumentEditActivity extends AppCompatActivity {
// Cancellable progress dialog // Cancellable progress dialog
final ProgressDialog progressDialog = ProgressDialog.show(this, final ProgressDialog progressDialog = ProgressDialog.show(this,
getString(R.string.please_wait), getString(R.string.please_wait),
getString(R.string.document_editing_message), true, true, getString(R.string.document_editing_message), true, true);
new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
DocumentResource.cancel(DocumentEditActivity.this);
}
});
// Server callback // Server callback
HttpCallback callback = new HttpCallback() { HttpCallback callback = new HttpCallback() {

View File

@ -1,16 +1,13 @@
package com.sismics.docs.activity; package com.sismics.docs.activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.DownloadManager;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.ClipData; import android.content.ClipData;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v4.view.GravityCompat; import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager;
@ -47,15 +44,18 @@ import com.sismics.docs.event.FileDeleteEvent;
import com.sismics.docs.fragment.DocExportPdfFragment; import com.sismics.docs.fragment.DocExportPdfFragment;
import com.sismics.docs.fragment.DocShareFragment; import com.sismics.docs.fragment.DocShareFragment;
import com.sismics.docs.listener.HttpCallback; import com.sismics.docs.listener.HttpCallback;
import com.sismics.docs.listener.JsonHttpResponseHandler;
import com.sismics.docs.model.application.ApplicationContext; import com.sismics.docs.model.application.ApplicationContext;
import com.sismics.docs.resource.CommentResource; import com.sismics.docs.resource.CommentResource;
import com.sismics.docs.resource.DocumentResource; import com.sismics.docs.resource.DocumentResource;
import com.sismics.docs.resource.FileResource; import com.sismics.docs.resource.FileResource;
import com.sismics.docs.service.FileUploadService; import com.sismics.docs.service.FileUploadService;
import com.sismics.docs.util.NetworkUtil;
import com.sismics.docs.util.PreferenceUtil; import com.sismics.docs.util.PreferenceUtil;
import com.sismics.docs.util.TagUtil; import com.sismics.docs.util.TagUtil;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -64,9 +64,6 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import cz.msebera.android.httpclient.Header;
import de.greenrobot.event.EventBus;
/** /**
* Document activity. * Document activity.
* *
@ -183,7 +180,7 @@ public class DocumentViewActivity extends AppCompatActivity {
createdDateTextView.setText(date); createdDateTextView.setText(date);
TextView descriptionTextView = (TextView) findViewById(R.id.descriptionTextView); TextView descriptionTextView = (TextView) findViewById(R.id.descriptionTextView);
if (description == null || description.isEmpty() || description.equals(JSONObject.NULL.toString())) { if (description.isEmpty() || document.isNull("description")) {
descriptionTextView.setVisibility(View.GONE); descriptionTextView.setVisibility(View.GONE);
} else { } else {
descriptionTextView.setVisibility(View.VISIBLE); descriptionTextView.setVisibility(View.VISIBLE);
@ -251,7 +248,8 @@ public class DocumentViewActivity extends AppCompatActivity {
button.setOnClickListener(new View.OnClickListener() { button.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
DialogFragment dialog = DocExportPdfFragment.newInstance(DocumentViewActivity.this.document.optString("id")); DialogFragment dialog = DocExportPdfFragment.newInstance(
DocumentViewActivity.this.document.optString("id"), DocumentViewActivity.this.document.optString("title"));
dialog.show(getSupportFragmentManager(), "DocExportPdfFragment"); dialog.show(getSupportFragmentManager(), "DocExportPdfFragment");
} }
}); });
@ -282,14 +280,14 @@ public class DocumentViewActivity extends AppCompatActivity {
CommentResource.add(DocumentViewActivity.this, CommentResource.add(DocumentViewActivity.this,
DocumentViewActivity.this.document.optString("id"), DocumentViewActivity.this.document.optString("id"),
commentEditText.getText().toString(), commentEditText.getText().toString(),
new JsonHttpResponseHandler() { new HttpCallback() {
public void onSuccess(int statusCode, Header[] headers, JSONObject response) { public void onSuccess(JSONObject response) {
EventBus.getDefault().post(new CommentAddEvent(response)); EventBus.getDefault().post(new CommentAddEvent(response));
commentEditText.setText(""); commentEditText.setText("");
} }
@Override @Override
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { public void onFailure(JSONObject json, Exception e) {
Toast.makeText(DocumentViewActivity.this, R.string.comment_add_failure, Toast.LENGTH_LONG).show(); Toast.makeText(DocumentViewActivity.this, R.string.comment_add_failure, Toast.LENGTH_LONG).show();
} }
}); });
@ -366,11 +364,11 @@ public class DocumentViewActivity extends AppCompatActivity {
int position = fileViewPager.getCurrentItem(); int position = fileViewPager.getCurrentItem();
if (mimeType == null || !mimeType.contains("/")) return; if (mimeType == null || !mimeType.contains("/")) return;
String ext = mimeType.split("/")[1]; String ext = mimeType.split("/")[1];
String fileName = getTitle() + "-" + position + "." + ext; String fileName = document.optString("title") + "-" + position + "." + ext;
// Download the file // Download the file
String fileUrl = PreferenceUtil.getServerUrl(this) + "/api/file/" + file.optString("id") + "/data"; String fileUrl = PreferenceUtil.getServerUrl(this) + "/api/file/" + file.optString("id") + "/data";
downloadFile(fileUrl, fileName, getTitle().toString(), getString(R.string.downloading_file, position + 1)); NetworkUtil.downloadFile(this, fileUrl, fileName, document.optString("title"), getString(R.string.download_file_title));
} }
private void deleteCurrentFile() { private void deleteCurrentFile() {
@ -393,24 +391,18 @@ public class DocumentViewActivity extends AppCompatActivity {
// Show a progress dialog while deleting // Show a progress dialog while deleting
final ProgressDialog progressDialog = ProgressDialog.show(DocumentViewActivity.this, final ProgressDialog progressDialog = ProgressDialog.show(DocumentViewActivity.this,
getString(R.string.please_wait), getString(R.string.please_wait),
getString(R.string.file_deleting_message), true, true, getString(R.string.file_deleting_message), true, true);
new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
FileResource.cancel(DocumentViewActivity.this);
}
});
// Actual delete server call // Actual delete server call
final String fileId = file.optString("id"); final String fileId = file.optString("id");
FileResource.delete(DocumentViewActivity.this, fileId, new JsonHttpResponseHandler() { FileResource.delete(DocumentViewActivity.this, fileId, new HttpCallback() {
@Override @Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) { public void onSuccess(JSONObject response) {
EventBus.getDefault().post(new FileDeleteEvent(fileId)); EventBus.getDefault().post(new FileDeleteEvent(fileId));
} }
@Override @Override
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { public void onFailure(JSONObject json, Exception e) {
Toast.makeText(DocumentViewActivity.this, R.string.file_delete_failure, Toast.LENGTH_LONG).show(); Toast.makeText(DocumentViewActivity.this, R.string.file_delete_failure, Toast.LENGTH_LONG).show();
} }
@ -435,28 +427,8 @@ public class DocumentViewActivity extends AppCompatActivity {
private void downloadZip() { private void downloadZip() {
if (document == null) return; if (document == null) return;
String url = PreferenceUtil.getServerUrl(this) + "/api/file/zip?id=" + document.optString("id"); String url = PreferenceUtil.getServerUrl(this) + "/api/file/zip?id=" + document.optString("id");
String fileName = getTitle() + ".zip"; String fileName = document.optString("title") + ".zip";
downloadFile(url, fileName, getTitle().toString(), getString(R.string.downloading_document)); NetworkUtil.downloadFile(this, url, fileName, document.optString("title"), getString(R.string.download_document_title));
}
/**
* Download a file using Android download manager.
*
* @param url URL to download
* @param fileName Destination file name
* @param title Notification title
* @param description Notification description
*/
private void downloadFile(String url, String fileName, String title, String description) {
String authToken = PreferenceUtil.getAuthToken(this);
DownloadManager downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
request.addRequestHeader("Cookie", "auth_token=" + authToken);
request.setTitle(title);
request.setDescription(description);
downloadManager.enqueue(request);
} }
/** /**
@ -478,13 +450,7 @@ public class DocumentViewActivity extends AppCompatActivity {
// Show a progress dialog while deleting // Show a progress dialog while deleting
final ProgressDialog progressDialog = ProgressDialog.show(DocumentViewActivity.this, final ProgressDialog progressDialog = ProgressDialog.show(DocumentViewActivity.this,
getString(R.string.please_wait), getString(R.string.please_wait),
getString(R.string.document_deleting_message), true, true, getString(R.string.document_deleting_message), true, true);
new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
DocumentResource.cancel(DocumentViewActivity.this);
}
});
// Actual delete server call // Actual delete server call
final String documentId = document.optString("id"); final String documentId = document.optString("id");
@ -520,6 +486,7 @@ public class DocumentViewActivity extends AppCompatActivity {
* *
* @param event Document fullscreen event * @param event Document fullscreen event
*/ */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(DocumentFullscreenEvent event) { public void onEventMainThread(DocumentFullscreenEvent event) {
findViewById(R.id.detailLayout).setVisibility(event.isFullscreen() ? View.GONE : View.VISIBLE); findViewById(R.id.detailLayout).setVisibility(event.isFullscreen() ? View.GONE : View.VISIBLE);
} }
@ -529,6 +496,7 @@ public class DocumentViewActivity extends AppCompatActivity {
* *
* @param event Document edit event * @param event Document edit event
*/ */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(DocumentEditEvent event) { public void onEventMainThread(DocumentEditEvent event) {
if (document == null) return; if (document == null) return;
if (event.getDocument().optString("id").equals(document.optString("id"))) { if (event.getDocument().optString("id").equals(document.optString("id"))) {
@ -542,6 +510,7 @@ public class DocumentViewActivity extends AppCompatActivity {
* *
* @param event Document delete event * @param event Document delete event
*/ */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(DocumentDeleteEvent event) { public void onEventMainThread(DocumentDeleteEvent event) {
if (document == null) return; if (document == null) return;
if (event.getDocumentId().equals(document.optString("id"))) { if (event.getDocumentId().equals(document.optString("id"))) {
@ -555,6 +524,7 @@ public class DocumentViewActivity extends AppCompatActivity {
* *
* @param event File delete event * @param event File delete event
*/ */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(FileDeleteEvent event) { public void onEventMainThread(FileDeleteEvent event) {
if (filePagerAdapter == null) return; if (filePagerAdapter == null) return;
filePagerAdapter.remove(event.getFileId()); filePagerAdapter.remove(event.getFileId());
@ -567,6 +537,7 @@ public class DocumentViewActivity extends AppCompatActivity {
* *
* @param event File add event * @param event File add event
*/ */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(FileAddEvent event) { public void onEventMainThread(FileAddEvent event) {
if (document == null) return; if (document == null) return;
if (document.optString("id").equals(event.getDocumentId())) { if (document.optString("id").equals(event.getDocumentId())) {
@ -579,6 +550,7 @@ public class DocumentViewActivity extends AppCompatActivity {
* *
* @param event Comment add event * @param event Comment add event
*/ */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(CommentAddEvent event) { public void onEventMainThread(CommentAddEvent event) {
if (commentListAdapter == null) return; if (commentListAdapter == null) return;
TextView emptyView = (TextView) findViewById(R.id.commentEmptyView); TextView emptyView = (TextView) findViewById(R.id.commentEmptyView);
@ -593,6 +565,7 @@ public class DocumentViewActivity extends AppCompatActivity {
* *
* @param event Comment add event * @param event Comment add event
*/ */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(CommentDeleteEvent event) { public void onEventMainThread(CommentDeleteEvent event) {
if (commentListAdapter == null) return; if (commentListAdapter == null) return;
TextView emptyView = (TextView) findViewById(R.id.commentEmptyView); TextView emptyView = (TextView) findViewById(R.id.commentEmptyView);
@ -696,14 +669,14 @@ public class DocumentViewActivity extends AppCompatActivity {
final String commentId = comment.optString("id"); final String commentId = comment.optString("id");
Toast.makeText(DocumentViewActivity.this, R.string.deleting_comment, Toast.LENGTH_LONG).show(); Toast.makeText(DocumentViewActivity.this, R.string.deleting_comment, Toast.LENGTH_LONG).show();
CommentResource.remove(DocumentViewActivity.this, commentId, new JsonHttpResponseHandler() { CommentResource.remove(DocumentViewActivity.this, commentId, new HttpCallback() {
@Override @Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) { public void onSuccess(JSONObject response) {
EventBus.getDefault().post(new CommentDeleteEvent(commentId)); EventBus.getDefault().post(new CommentDeleteEvent(commentId));
} }
@Override @Override
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { public void onFailure(JSONObject json, Exception e) {
Toast.makeText(DocumentViewActivity.this, R.string.error_deleting_comment, Toast.LENGTH_LONG).show(); Toast.makeText(DocumentViewActivity.this, R.string.error_deleting_comment, Toast.LENGTH_LONG).show();
} }
}); });
@ -728,9 +701,9 @@ public class DocumentViewActivity extends AppCompatActivity {
listView.setVisibility(View.GONE); listView.setVisibility(View.GONE);
registerForContextMenu(listView); registerForContextMenu(listView);
CommentResource.list(this, document.optString("id"), new JsonHttpResponseHandler() { CommentResource.list(this, document.optString("id"), new HttpCallback() {
@Override @Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) { public void onSuccess(JSONObject response) {
JSONArray comments = response.optJSONArray("comments"); JSONArray comments = response.optJSONArray("comments");
commentListAdapter = new CommentListAdapter(DocumentViewActivity.this, comments); commentListAdapter = new CommentListAdapter(DocumentViewActivity.this, comments);
listView.setAdapter(commentListAdapter); listView.setAdapter(commentListAdapter);
@ -743,7 +716,7 @@ public class DocumentViewActivity extends AppCompatActivity {
} }
@Override @Override
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { public void onFailure(JSONObject json, Exception e) {
emptyView.setText(R.string.error_loading_comments); emptyView.setText(R.string.error_loading_comments);
progressBar.setVisibility(View.GONE); progressBar.setVisibility(View.GONE);
listView.setVisibility(View.GONE); listView.setVisibility(View.GONE);
@ -766,9 +739,9 @@ public class DocumentViewActivity extends AppCompatActivity {
progressBar.setVisibility(View.VISIBLE); progressBar.setVisibility(View.VISIBLE);
filesEmptyView.setVisibility(View.GONE); filesEmptyView.setVisibility(View.GONE);
FileResource.list(this, document.optString("id"), new JsonHttpResponseHandler() { FileResource.list(this, document.optString("id"), new HttpCallback() {
@Override @Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) { public void onSuccess(JSONObject response) {
JSONArray files = response.optJSONArray("files"); JSONArray files = response.optJSONArray("files");
filePagerAdapter = new FilePagerAdapter(DocumentViewActivity.this, files); filePagerAdapter = new FilePagerAdapter(DocumentViewActivity.this, files);
fileViewPager.setAdapter(filePagerAdapter); fileViewPager.setAdapter(filePagerAdapter);
@ -778,7 +751,7 @@ public class DocumentViewActivity extends AppCompatActivity {
} }
@Override @Override
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { public void onFailure(JSONObject json, Exception e) {
filesEmptyView.setText(R.string.error_loading_files); filesEmptyView.setText(R.string.error_loading_files);
progressBar.setVisibility(View.GONE); progressBar.setVisibility(View.GONE);
filesEmptyView.setVisibility(View.VISIBLE); filesEmptyView.setVisibility(View.VISIBLE);

View File

@ -14,7 +14,7 @@ import android.widget.TextView;
import com.sismics.docs.R; import com.sismics.docs.R;
import com.sismics.docs.listener.CallbackListener; import com.sismics.docs.listener.CallbackListener;
import com.sismics.docs.listener.JsonHttpResponseHandler; import com.sismics.docs.listener.HttpCallback;
import com.sismics.docs.model.application.ApplicationContext; import com.sismics.docs.model.application.ApplicationContext;
import com.sismics.docs.resource.UserResource; import com.sismics.docs.resource.UserResource;
import com.sismics.docs.ui.form.Validator; import com.sismics.docs.ui.form.Validator;
@ -24,8 +24,6 @@ import com.sismics.docs.util.PreferenceUtil;
import org.json.JSONObject; import org.json.JSONObject;
import cz.msebera.android.httpclient.Header;
/** /**
* Login activity. * Login activity.
* *
@ -90,9 +88,9 @@ public class LoginActivity extends AppCompatActivity {
PreferenceUtil.setServerUrl(LoginActivity.this, txtServer.getText().toString()); PreferenceUtil.setServerUrl(LoginActivity.this, txtServer.getText().toString());
try { try {
UserResource.login(getApplicationContext(), txtUsername.getText().toString(), txtPassword.getText().toString(), new JsonHttpResponseHandler() { UserResource.login(getApplicationContext(), txtUsername.getText().toString(), txtPassword.getText().toString(), new HttpCallback() {
@Override @Override
public void onSuccess(int statusCode, Header[] headers, JSONObject json) { public void onSuccess(JSONObject json) {
// Empty previous user caches // Empty previous user caches
PreferenceUtil.resetUserCache(getApplicationContext()); PreferenceUtil.resetUserCache(getApplicationContext());
@ -108,11 +106,11 @@ public class LoginActivity extends AppCompatActivity {
} }
@Override @Override
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { public void onFailure(JSONObject json, Exception e) {
loginForm.setVisibility(View.VISIBLE); loginForm.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE); progressBar.setVisibility(View.GONE);
if (responseBytes != null && new String(responseBytes).contains("\"ForbiddenError\"")) { if (json != null && json.optString("type").equals("ForbiddenError")) {
DialogUtil.showOkDialog(LoginActivity.this, R.string.login_fail_title, R.string.login_fail); DialogUtil.showOkDialog(LoginActivity.this, R.string.login_fail_title, R.string.login_fail);
} else { } else {
DialogUtil.showOkDialog(LoginActivity.this, R.string.network_error_title, R.string.network_error); DialogUtil.showOkDialog(LoginActivity.this, R.string.network_error_title, R.string.network_error);
@ -150,9 +148,9 @@ public class LoginActivity extends AppCompatActivity {
finish(); finish();
} else { } else {
// Trying to get user data // Trying to get user data
UserResource.info(getApplicationContext(), new JsonHttpResponseHandler() { UserResource.info(getApplicationContext(), new HttpCallback() {
@Override @Override
public void onSuccess(int statusCode, Header[] headers, final JSONObject json) { public void onSuccess(final JSONObject json) {
if (json.optBoolean("anonymous", true)) { if (json.optBoolean("anonymous", true)) {
loginForm.setVisibility(View.VISIBLE); loginForm.setVisibility(View.VISIBLE);
return; return;
@ -168,7 +166,7 @@ public class LoginActivity extends AppCompatActivity {
} }
@Override @Override
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { public void onFailure(JSONObject json, Exception e) {
DialogUtil.showOkDialog(LoginActivity.this, R.string.network_error_title, R.string.network_error); DialogUtil.showOkDialog(LoginActivity.this, R.string.network_error_title, R.string.network_error);
loginForm.setVisibility(View.VISIBLE); loginForm.setVisibility(View.VISIBLE);
} }

View File

@ -23,18 +23,18 @@ import com.sismics.docs.adapter.TagListAdapter;
import com.sismics.docs.event.AdvancedSearchEvent; import com.sismics.docs.event.AdvancedSearchEvent;
import com.sismics.docs.event.SearchEvent; import com.sismics.docs.event.SearchEvent;
import com.sismics.docs.fragment.SearchFragment; import com.sismics.docs.fragment.SearchFragment;
import com.sismics.docs.listener.JsonHttpResponseHandler; import com.sismics.docs.listener.HttpCallback;
import com.sismics.docs.model.application.ApplicationContext; import com.sismics.docs.model.application.ApplicationContext;
import com.sismics.docs.provider.RecentSuggestionsProvider; import com.sismics.docs.provider.RecentSuggestionsProvider;
import com.sismics.docs.resource.TagResource; import com.sismics.docs.resource.TagResource;
import com.sismics.docs.resource.UserResource; import com.sismics.docs.resource.UserResource;
import com.sismics.docs.util.PreferenceUtil; import com.sismics.docs.util.PreferenceUtil;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONObject; import org.json.JSONObject;
import cz.msebera.android.httpclient.Header;
import de.greenrobot.event.EventBus;
/** /**
* Main activity. * Main activity.
* *
@ -90,9 +90,9 @@ public class MainActivity extends AppCompatActivity {
if (cacheTags != null) { if (cacheTags != null) {
tagListView.setAdapter(new TagListAdapter(cacheTags.optJSONArray("stats"))); tagListView.setAdapter(new TagListAdapter(cacheTags.optJSONArray("stats")));
} }
TagResource.stats(this, new JsonHttpResponseHandler() { TagResource.stats(this, new HttpCallback() {
@Override @Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) { public void onSuccess(JSONObject response) {
PreferenceUtil.setCachedJson(MainActivity.this, PreferenceUtil.PREF_CACHED_TAGS_JSON, response); PreferenceUtil.setCachedJson(MainActivity.this, PreferenceUtil.PREF_CACHED_TAGS_JSON, response);
tagListView.setAdapter(new TagListAdapter(response.optJSONArray("stats"))); tagListView.setAdapter(new TagListAdapter(response.optJSONArray("stats")));
tagProgressView.setVisibility(View.GONE); tagProgressView.setVisibility(View.GONE);
@ -100,7 +100,7 @@ public class MainActivity extends AppCompatActivity {
} }
@Override @Override
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { public void onFailure(JSONObject json, Exception e) {
tagEmptyView.setText(R.string.error_loading_tags); tagEmptyView.setText(R.string.error_loading_tags);
tagProgressView.setVisibility(View.GONE); tagProgressView.setVisibility(View.GONE);
tagListView.setEmptyView(tagEmptyView); tagListView.setEmptyView(tagEmptyView);
@ -146,7 +146,7 @@ public class MainActivity extends AppCompatActivity {
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.logout: case R.id.logout:
UserResource.logout(getApplicationContext(), new JsonHttpResponseHandler() { UserResource.logout(getApplicationContext(), new HttpCallback() {
@Override @Override
public void onFinish() { public void onFinish() {
// Force logout in all cases, so the user is not stuck in case of network error // Force logout in all cases, so the user is not stuck in case of network error
@ -266,6 +266,7 @@ public class MainActivity extends AppCompatActivity {
* *
* @param event Advanced search event * @param event Advanced search event
*/ */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(AdvancedSearchEvent event) { public void onEventMainThread(AdvancedSearchEvent event) {
searchQuery(event.getQuery()); searchQuery(event.getQuery());
} }

View File

@ -36,11 +36,6 @@ public class FilePagerAdapter extends PagerAdapter {
*/ */
private Context context; private Context context;
/**
* Auth token used to download files.
*/
private String authToken;
/** /**
* File pager adapter. * File pager adapter.
* *
@ -53,7 +48,6 @@ public class FilePagerAdapter extends PagerAdapter {
files.add(filesArray.optJSONObject(i)); files.add(filesArray.optJSONObject(i));
} }
this.context = context; this.context = context;
this.authToken = PreferenceUtil.getAuthToken(context);
} }
@Override @Override

View File

@ -12,14 +12,13 @@ import com.sismics.docs.R;
import com.sismics.docs.event.ShareDeleteEvent; import com.sismics.docs.event.ShareDeleteEvent;
import com.sismics.docs.event.ShareSendEvent; import com.sismics.docs.event.ShareSendEvent;
import org.greenrobot.eventbus.EventBus;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import de.greenrobot.event.EventBus;
/** /**
* Share list adapter. * Share list adapter.
* *

View File

@ -20,6 +20,7 @@ import org.json.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale;
/** /**
* Tag list adapter. * Tag list adapter.
@ -99,7 +100,7 @@ public class TagListAdapter extends BaseAdapter {
TextView tagTextView = (TextView) view.findViewById(R.id.tagTextView); TextView tagTextView = (TextView) view.findViewById(R.id.tagTextView);
tagTextView.setText(tagItem.name); tagTextView.setText(tagItem.name);
TextView tagCountTextView = (TextView) view.findViewById(R.id.tagCountTextView); TextView tagCountTextView = (TextView) view.findViewById(R.id.tagCountTextView);
tagCountTextView.setText(String.format("%d", tagItem.count)); tagCountTextView.setText(String.format(Locale.ENGLISH, "%d", tagItem.count));
// Label color filtering // Label color filtering
ImageView labelImageView = (ImageView) view.findViewById(R.id.labelImageView); ImageView labelImageView = (ImageView) view.findViewById(R.id.labelImageView);

View File

@ -8,8 +8,15 @@ import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.TextView;
import com.sismics.docs.R; import com.sismics.docs.R;
import com.sismics.docs.util.NetworkUtil;
import com.sismics.docs.util.PreferenceUtil;
import java.util.Locale;
/** /**
* Export PDF dialog fragment. * Export PDF dialog fragment.
@ -21,11 +28,13 @@ public class DocExportPdfFragment extends DialogFragment {
* Export PDF dialog fragment. * Export PDF dialog fragment.
* *
* @param id Document ID * @param id Document ID
* @param title Document title
*/ */
public static DocExportPdfFragment newInstance(String id) { public static DocExportPdfFragment newInstance(String id, String title) {
DocExportPdfFragment fragment = new DocExportPdfFragment(); DocExportPdfFragment fragment = new DocExportPdfFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString("id", id); args.putString("id", id);
args.putString("title", title);
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@ -38,11 +47,41 @@ public class DocExportPdfFragment extends DialogFragment {
// Setup the view // Setup the view
LayoutInflater inflater = getActivity().getLayoutInflater(); LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.document_export_pdf_dialog, null); View view = inflater.inflate(R.layout.document_export_pdf_dialog, null);
final SeekBar marginSeekBar = (SeekBar) view.findViewById(R.id.marginSeekBar);
final CheckBox exportMetadataCheckbox = (CheckBox) view.findViewById(R.id.exportMetadataCheckbox);
final CheckBox exportCommentsCheckbox = (CheckBox) view.findViewById(R.id.exportCommentsCheckbox);
final CheckBox fitToPageCheckbox = (CheckBox) view.findViewById(R.id.fitToPageCheckbox);
final TextView marginValueText = (TextView) view.findViewById(R.id.marginValueText);
// Margin label follow seekbar value
marginSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
marginValueText.setText(String.format(Locale.ENGLISH, "%d", progress));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// Build the dialog // Build the dialog
builder.setView(view) builder.setView(view)
.setPositiveButton(R.string.download, new DialogInterface.OnClickListener() { .setPositiveButton(R.string.download, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
// Download the PDF
String pdfUrl = PreferenceUtil.getServerUrl(getActivity()) + "/api/document/" + getArguments().getString("id") + "/pdf?" +
"metadata=" + exportMetadataCheckbox.isChecked() + "&comments=" + exportCommentsCheckbox.isChecked() + "&fitimagetopage=" + fitToPageCheckbox.isChecked() +
"&margin=" + marginSeekBar.getProgress();
String title = getArguments().getString("title");
NetworkUtil.downloadFile(getActivity(), pdfUrl, title + ".pdf", title, getString(R.string.download_pdf_title));
getDialog().cancel(); getDialog().cancel();
} }
}) })

View File

@ -27,10 +27,11 @@ import com.sismics.docs.resource.DocumentResource;
import com.sismics.docs.ui.view.DividerItemDecoration; import com.sismics.docs.ui.view.DividerItemDecoration;
import com.sismics.docs.ui.view.EmptyRecyclerView; import com.sismics.docs.ui.view.EmptyRecyclerView;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONObject; import org.json.JSONObject;
import de.greenrobot.event.EventBus;
/** /**
* @author bgamard. * @author bgamard.
*/ */
@ -99,7 +100,7 @@ public class DocListFragment extends Fragment {
})); }));
// Infinite scrolling // Infinite scrolling
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override @Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) { public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy); super.onScrolled(recyclerView, dx, dy);
@ -149,6 +150,7 @@ public class DocListFragment extends Fragment {
* *
* @param event Search event * @param event Search event
*/ */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(SearchEvent event) { public void onEventMainThread(SearchEvent event) {
query = event.getQuery(); query = event.getQuery();
loadDocuments(getView(), true); loadDocuments(getView(), true);
@ -159,6 +161,7 @@ public class DocListFragment extends Fragment {
* *
* @param event Document edit event * @param event Document edit event
*/ */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(DocumentEditEvent event) { public void onEventMainThread(DocumentEditEvent event) {
adapter.updateDocument(event.getDocument()); adapter.updateDocument(event.getDocument());
} }
@ -168,6 +171,7 @@ public class DocListFragment extends Fragment {
* *
* @param event Document delete event * @param event Document delete event
*/ */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(DocumentDeleteEvent event) { public void onEventMainThread(DocumentDeleteEvent event) {
adapter.deleteDocument(event.getDocumentId()); adapter.deleteDocument(event.getDocumentId());
} }
@ -177,6 +181,7 @@ public class DocListFragment extends Fragment {
* *
* @param event Document add event * @param event Document add event
*/ */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(DocumentAddEvent event) { public void onEventMainThread(DocumentAddEvent event) {
// Refresh the list, maybe the new document fit in it // Refresh the list, maybe the new document fit in it
loadDocuments(getView(), true); loadDocuments(getView(), true);

View File

@ -22,17 +22,16 @@ import com.sismics.docs.adapter.ShareListAdapter;
import com.sismics.docs.event.ShareDeleteEvent; import com.sismics.docs.event.ShareDeleteEvent;
import com.sismics.docs.event.ShareSendEvent; import com.sismics.docs.event.ShareSendEvent;
import com.sismics.docs.listener.HttpCallback; import com.sismics.docs.listener.HttpCallback;
import com.sismics.docs.listener.JsonHttpResponseHandler;
import com.sismics.docs.resource.DocumentResource; import com.sismics.docs.resource.DocumentResource;
import com.sismics.docs.resource.ShareResource; import com.sismics.docs.resource.ShareResource;
import com.sismics.docs.util.PreferenceUtil; import com.sismics.docs.util.PreferenceUtil;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import cz.msebera.android.httpclient.Header;
import de.greenrobot.event.EventBus;
/** /**
* Document sharing dialog fragment. * Document sharing dialog fragment.
* *
@ -76,15 +75,15 @@ public class DocShareFragment extends DialogFragment {
shareAddButton.setEnabled(false); shareAddButton.setEnabled(false);
ShareResource.add(getActivity(), getArguments().getString("id"), shareNameEditText.getText().toString(), ShareResource.add(getActivity(), getArguments().getString("id"), shareNameEditText.getText().toString(),
new JsonHttpResponseHandler() { new HttpCallback() {
@Override @Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) { public void onSuccess(JSONObject response) {
shareNameEditText.setText(""); shareNameEditText.setText("");
loadShares(getDialog().getWindow().getDecorView()); loadShares(getDialog().getWindow().getDecorView());
} }
@Override @Override
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { public void onFailure(JSONObject json, Exception e) {
Toast.makeText(getActivity(), R.string.error_adding_share, Toast.LENGTH_SHORT).show(); Toast.makeText(getActivity(), R.string.error_adding_share, Toast.LENGTH_SHORT).show();
} }
@ -141,20 +140,32 @@ public class DocShareFragment extends DialogFragment {
}); });
} }
/**
* A share delete event has been fired.
*
* @param event Share delete event
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(ShareDeleteEvent event) { public void onEventMainThread(ShareDeleteEvent event) {
ShareResource.delete(getActivity(), event.getId(), new JsonHttpResponseHandler() { ShareResource.delete(getActivity(), event.getId(), new HttpCallback() {
@Override @Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) { public void onSuccess(JSONObject response) {
loadShares(getDialog().getWindow().getDecorView()); loadShares(getDialog().getWindow().getDecorView());
} }
@Override @Override
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { public void onFailure(JSONObject json, Exception e) {
Toast.makeText(getActivity(), R.string.error_deleting_share, Toast.LENGTH_SHORT).show(); Toast.makeText(getActivity(), R.string.error_deleting_share, Toast.LENGTH_SHORT).show();
} }
}); });
} }
/**
* A share send event has been fired.
*
* @param event Share send event
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(ShareSendEvent event) { public void onEventMainThread(ShareSendEvent event) {
if (document == null) return; if (document == null) return;

View File

@ -22,14 +22,13 @@ import com.sismics.docs.ui.view.TagsCompleteTextView;
import com.sismics.docs.util.PreferenceUtil; import com.sismics.docs.util.PreferenceUtil;
import com.sismics.docs.util.SearchQueryBuilder; import com.sismics.docs.util.SearchQueryBuilder;
import org.greenrobot.eventbus.EventBus;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import de.greenrobot.event.EventBus;
/** /**
* Advanced search fragment. * Advanced search fragment.
* *

View File

@ -1,242 +0,0 @@
/*
Android Asynchronous Http Client
Copyright (c) 2011 James Smith <james@loopj.com>
http://loopj.com
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 com.sismics.docs.listener;
import android.util.Log;
import com.loopj.android.http.TextHttpResponseHandler;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import cz.msebera.android.httpclient.Header;
import cz.msebera.android.httpclient.HttpStatus;
/**
* Used to intercept and handle the responses from requests made using {@link com.loopj.android.http.AsyncHttpClient}, with
* automatic parsing into a {@link JSONObject} or {@link JSONArray}. <p>&nbsp;</p> This class is
* designed to be passed to get, post, put and delete requests with the {@link #onSuccess(int,
* cz.msebera.android.httpclient.Header[], org.json.JSONArray)} or {@link #onSuccess(int,
* cz.msebera.android.httpclient.Header[], org.json.JSONObject)} methods anonymously overridden. <p>&nbsp;</p>
* Additionally, you can override the other event methods from the parent class.
*/
public class JsonHttpResponseHandler extends TextHttpResponseHandler {
private static final String LOG_TAG = "JsonHttpResponseHandler";
/**
* Creates new JsonHttpResponseHandler, with JSON String encoding UTF-8
*/
public JsonHttpResponseHandler() {
super(DEFAULT_CHARSET);
}
/**
* Creates new JsonHttpRespnseHandler with given JSON String encoding
*
* @param encoding String encoding to be used when parsing JSON
*/
public JsonHttpResponseHandler(String encoding) {
super(encoding);
}
/**
* Returns when request succeeds
*
* @param statusCode http response status line
* @param headers response headers if any
* @param response parsed response if any
*/
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
Log.w(LOG_TAG, "onSuccess(int, Header[], JSONObject) was not overriden, but callback was received");
}
/**
* Returns when request succeeds
*
* @param statusCode http response status line
* @param headers response headers if any
* @param response parsed response if any
*/
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
Log.w(LOG_TAG, "onSuccess(int, Header[], JSONArray) was not overriden, but callback was received");
}
/**
* Returns when request failed
*
* @param statusCode http response status line
* @param headers response headers if any
* @param throwable throwable describing the way request failed
* @param errorResponse parsed response if any
*/
public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) {
Log.w(LOG_TAG, "onFailure(int, Header[], Throwable, JSONObject) was not overriden, but callback was received", throwable);
}
/**
* Returns when request failed
*
* @param statusCode http response status line
* @param headers response headers if any
* @param throwable throwable describing the way request failed
* @param errorResponse parsed response if any
*/
public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONArray errorResponse) {
Log.w(LOG_TAG, "onFailure(int, Header[], Throwable, JSONArray) was not overriden, but callback was received", throwable);
}
@Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
Log.w(LOG_TAG, "onFailure(int, Header[], String, Throwable) was not overriden, but callback was received", throwable);
}
@Override
public void onSuccess(int statusCode, Header[] headers, String responseString) {
Log.w(LOG_TAG, "onSuccess(int, Header[], String) was not overriden, but callback was received");
}
@Override
public final void onSuccess(final int statusCode, final Header[] headers, final byte[] responseBytes) {
if (statusCode != HttpStatus.SC_NO_CONTENT) {
Runnable parser = new Runnable() {
@Override
public void run() {
try {
final Object jsonResponse = parseResponse(responseBytes);
postRunnable(new Runnable() {
@Override
public void run() {
if (jsonResponse instanceof JSONObject) {
onSuccess(statusCode, headers, (JSONObject) jsonResponse);
} else if (jsonResponse instanceof JSONArray) {
onSuccess(statusCode, headers, (JSONArray) jsonResponse);
} else if (jsonResponse instanceof String) {
onFailure(statusCode, headers, (String) jsonResponse, new JSONException("Response cannot be parsed as JSON data"));
} else {
onFailure(statusCode, headers, new JSONException("Unexpected response type " + jsonResponse.getClass().getName()), (JSONObject) null);
}
}
});
} catch (final JSONException ex) {
postRunnable(new Runnable() {
@Override
public void run() {
onFailure(statusCode, headers, ex, (JSONObject) null);
}
});
}
}
};
if (!getUseSynchronousMode()) {
new Thread(parser).start();
} else {
// In synchronous mode everything should be run on one thread
parser.run();
}
} else {
onSuccess(statusCode, headers, new JSONObject());
}
}
@Override
public final void onFailure(final int statusCode, final Header[] headers, final byte[] responseBytes, final Throwable throwable) {
if (responseBytes != null) {
Runnable parser = new Runnable() {
@Override
public void run() {
try {
final Object jsonResponse = parseResponse(responseBytes);
postRunnable(new Runnable() {
@Override
public void run() {
if (jsonResponse instanceof JSONObject) {
onFailure(statusCode, headers, throwable, (JSONObject) jsonResponse);
} else if (jsonResponse instanceof JSONArray) {
onFailure(statusCode, headers, throwable, (JSONArray) jsonResponse);
} else if (jsonResponse instanceof String) {
onFailure(statusCode, headers, (String) jsonResponse, throwable);
} else {
onFailure(statusCode, headers, new JSONException("Unexpected response type " + jsonResponse.getClass().getName()), (JSONObject) null);
}
}
});
} catch (final JSONException ex) {
postRunnable(new Runnable() {
@Override
public void run() {
onFailure(statusCode, headers, ex, (JSONObject) null);
}
});
}
}
};
if (!getUseSynchronousMode()) {
new Thread(parser).start();
} else {
// In synchronous mode everything should be run on one thread
parser.run();
}
} else {
Log.v(LOG_TAG, "response body is null, calling onFailure(Throwable, JSONObject)");
onFailure(statusCode, headers, throwable, (JSONObject) null);
}
// In all cases, call the default failure listener
onAllFailure(statusCode, headers, responseBytes, throwable);
}
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
// All failures go there
}
/**
* Returns Object of type {@link JSONObject}, {@link JSONArray}, String, Boolean, Integer, Long,
* Double or {@link JSONObject#NULL}, see {@link org.json.JSONTokener#nextValue()}
*
* @param responseBody response bytes to be assembled in String and parsed as JSON
* @return Object parsedResponse
* @throws org.json.JSONException exception if thrown while parsing JSON
*/
protected Object parseResponse(byte[] responseBody) throws JSONException {
if (null == responseBody)
return null;
Object result = null;
//trim the string to prevent start with blank, and test if the string is valid JSON, because the parser don't do this :(. If JSON is not valid this will return null
String jsonString = getResponseString(responseBody, getCharset());
if (jsonString != null) {
jsonString = jsonString.trim();
if (jsonString.startsWith(UTF8_BOM)) {
jsonString = jsonString.substring(1);
}
if (jsonString.startsWith("{") || jsonString.startsWith("[")) {
result = new JSONTokener(jsonString).nextValue();
}
}
if (result == null) {
result = jsonString;
}
return result;
}
}

View File

@ -29,7 +29,7 @@ public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListen
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) { public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY()); View childView = view.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) { if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildPosition(childView)); mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
} }
return false; return false;
} }

View File

@ -4,14 +4,12 @@ import android.app.Activity;
import android.content.Context; import android.content.Context;
import com.sismics.docs.listener.CallbackListener; import com.sismics.docs.listener.CallbackListener;
import com.sismics.docs.listener.JsonHttpResponseHandler; import com.sismics.docs.listener.HttpCallback;
import com.sismics.docs.resource.UserResource; import com.sismics.docs.resource.UserResource;
import com.sismics.docs.util.PreferenceUtil; import com.sismics.docs.util.PreferenceUtil;
import org.json.JSONObject; import org.json.JSONObject;
import cz.msebera.android.httpclient.Header;
/** /**
* Global context of the application. * Global context of the application.
* *
@ -81,9 +79,9 @@ public class ApplicationContext {
* @param callbackListener CallbackListener * @param callbackListener CallbackListener
*/ */
public void fetchUserInfo(final Activity activity, final CallbackListener callbackListener) { public void fetchUserInfo(final Activity activity, final CallbackListener callbackListener) {
UserResource.info(activity.getApplicationContext(), new JsonHttpResponseHandler() { UserResource.info(activity.getApplicationContext(), new HttpCallback() {
@Override @Override
public void onSuccess(int statusCode, Header[] headers, final JSONObject json) { public void onSuccess(JSONObject json) {
// Save data in application context // Save data in application context
if (!json.optBoolean("anonymous", true)) { if (!json.optBoolean("anonymous", true)) {
setUserInfo(activity.getApplicationContext(), json); setUserInfo(activity.getApplicationContext(), json);

View File

@ -1,124 +1,15 @@
package com.sismics.docs.resource; package com.sismics.docs.resource;
import android.content.Context; import android.content.Context;
import android.os.Build;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.PersistentCookieStore;
import com.sismics.docs.util.ApplicationUtil;
import com.sismics.docs.util.PreferenceUtil; import com.sismics.docs.util.PreferenceUtil;
import java.io.IOException;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Locale;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import cz.msebera.android.httpclient.conn.ssl.SSLSocketFactory;
/** /**
* Base class for API access. * Base class for API access.
* *
* @author bgamard * @author bgamard
*/ */
public class BaseResource { public class BaseResource {
/**
* User-Agent to use.
*/
protected static String USER_AGENT = null;
/**
* Accept-Language header.
*/
protected static String ACCEPT_LANGUAGE = null;
/**
* Async HTTP client.
*/
protected static AsyncHttpClient client = new AsyncHttpClient();
static {
// 20sec default timeout
client.setTimeout(60000);
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
// Async HTTP Client uses another HTTP libary
MySSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
client.setSSLSocketFactory(sf);
} catch (Exception e) {
// NOP
}
}
/**
* Resource initialization.
*
* @param context Context
*/
protected static void init(Context context) {
client.setCookieStore(new PersistentCookieStore(context));
if (USER_AGENT == null) {
USER_AGENT = "Sismics Docs Android " + ApplicationUtil.getVersionName(context) + "/Android " + Build.VERSION.RELEASE + "/" + Build.MODEL;
client.setUserAgent(USER_AGENT);
}
if (ACCEPT_LANGUAGE == null) {
Locale locale = Locale.getDefault();
ACCEPT_LANGUAGE = locale.getLanguage() + "_" + locale.getCountry();
client.addHeader("Accept-Language", ACCEPT_LANGUAGE);
}
}
/**
* Socket factory to allow self-signed certificates for Async HTTP Client.
*
* @author bgamard
*/
public static class MySSLSocketFactory extends cz.msebera.android.httpclient.conn.ssl.SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance(SSLSocketFactory.TLS);
public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[]{tm}, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}
/** /**
* Returns cleaned API URL. * Returns cleaned API URL.
* *

View File

@ -2,8 +2,12 @@ package com.sismics.docs.resource;
import android.content.Context; import android.content.Context;
import com.loopj.android.http.RequestParams; import com.sismics.docs.listener.HttpCallback;
import com.sismics.docs.listener.JsonHttpResponseHandler; import com.sismics.docs.util.OkHttpUtil;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Request;
/** /**
@ -17,12 +21,16 @@ public class CommentResource extends BaseResource {
* *
* @param context Context * @param context Context
* @param documentId Document ID * @param documentId Document ID
* @param responseHandler Callback * @param callback Callback
*/ */
public static void list(Context context, String documentId, JsonHttpResponseHandler responseHandler) { public static void list(Context context, String documentId, HttpCallback callback) {
init(context); Request request = new Request.Builder()
.url(HttpUrl.parse(getApiUrl(context) + "/comment/" + documentId))
client.get(getApiUrl(context) + "/comment/" + documentId, responseHandler); .get()
.build();
OkHttpUtil.buildClient(context)
.newCall(request)
.enqueue(HttpCallback.buildOkHttpCallback(callback));
} }
/** /**
@ -31,15 +39,19 @@ public class CommentResource extends BaseResource {
* @param context Context * @param context Context
* @param documentId Document ID * @param documentId Document ID
* @param content Comment content * @param content Comment content
* @param responseHandler Callback * @param callback Callback
*/ */
public static void add(Context context, String documentId, String content, JsonHttpResponseHandler responseHandler) { public static void add(Context context, String documentId, String content, HttpCallback callback) {
init(context); Request request = new Request.Builder()
.url(HttpUrl.parse(getApiUrl(context) + "/comment"))
RequestParams params = new RequestParams(); .put(new FormBody.Builder()
params.put("id", documentId); .add("id", documentId)
params.put("content", content); .add("content", content)
client.put(getApiUrl(context) + "/comment", params, responseHandler); .build())
.build();
OkHttpUtil.buildClient(context)
.newCall(request)
.enqueue(HttpCallback.buildOkHttpCallback(callback));
} }
/** /**
@ -47,20 +59,15 @@ public class CommentResource extends BaseResource {
* *
* @param context Context * @param context Context
* @param commentId Comment ID * @param commentId Comment ID
* @param responseHandler Callback * @param callback Callback
*/ */
public static void remove(Context context, String commentId, JsonHttpResponseHandler responseHandler) { public static void remove(Context context, String commentId, HttpCallback callback) {
init(context); Request request = new Request.Builder()
.url(HttpUrl.parse(getApiUrl(context) + "/comment/" + commentId))
client.delete(getApiUrl(context) + "/comment/" + commentId, responseHandler); .delete()
} .build();
OkHttpUtil.buildClient(context)
/** .newCall(request)
* Cancel pending requests. .enqueue(HttpCallback.buildOkHttpCallback(callback));
*
* @param context Context
*/
public static void cancel(Context context) {
client.cancelRequests(context, true);
} }
} }

View File

@ -94,9 +94,8 @@ public class DocumentResource extends BaseResource {
.add("description", description) .add("description", description)
.add("language", language) .add("language", language)
.add("create_date", Long.toString(createDate)); .add("create_date", Long.toString(createDate));
String[] tagIdArray = tagIdList.toArray(new String[tagIdList.size()]); for( String tagId : tagIdList) {
for (int i = 0; i < tagIdArray.length; i++) { formBuilder.add("tags", tagId);
formBuilder.add("tags", tagIdArray[i]);
} }
Request request = new Request.Builder() Request request = new Request.Builder()
@ -127,9 +126,8 @@ public class DocumentResource extends BaseResource {
.add("description", description) .add("description", description)
.add("language", language) .add("language", language)
.add("create_date", Long.toString(createDate)); .add("create_date", Long.toString(createDate));
String[] tagIdArray = tagIdList.toArray(new String[tagIdList.size()]); for( String tagId : tagIdList) {
for (int i = 0; i < tagIdArray.length; i++) { formBuilder.add("tags", tagId);
formBuilder.add("tags", tagIdArray[i]);
} }
Request request = new Request.Builder() Request request = new Request.Builder()
@ -140,13 +138,4 @@ public class DocumentResource extends BaseResource {
.newCall(request) .newCall(request)
.enqueue(HttpCallback.buildOkHttpCallback(callback)); .enqueue(HttpCallback.buildOkHttpCallback(callback));
} }
/**
* Cancel pending requests.
*
* @param context Context
*/
public static void cancel(Context context) {
client.cancelRequests(context, true);
}
} }

View File

@ -2,13 +2,24 @@ package com.sismics.docs.resource;
import android.content.Context; import android.content.Context;
import com.loopj.android.http.PersistentCookieStore; import com.sismics.docs.listener.HttpCallback;
import com.loopj.android.http.RequestParams; import com.sismics.docs.util.OkHttpUtil;
import com.loopj.android.http.SyncHttpClient;
import com.sismics.docs.listener.JsonHttpResponseHandler;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.KeyStore;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.internal.Util;
import okio.BufferedSink;
import okio.Okio;
import okio.Source;
/** /**
@ -22,12 +33,19 @@ public class FileResource extends BaseResource {
* *
* @param context Context * @param context Context
* @param documentId Document ID * @param documentId Document ID
* @param responseHandler Callback * @param callback Callback
*/ */
public static void list(Context context, String documentId, JsonHttpResponseHandler responseHandler) { public static void list(Context context, String documentId, HttpCallback callback) {
init(context); Request request = new Request.Builder()
.url(HttpUrl.parse(getApiUrl(context) + "/file/list")
client.get(getApiUrl(context) + "/file/list?id=" + documentId, responseHandler); .newBuilder()
.addQueryParameter("id", documentId)
.build())
.get()
.build();
OkHttpUtil.buildClient(context)
.newCall(request)
.enqueue(HttpCallback.buildOkHttpCallback(callback));
} }
/** /**
@ -35,12 +53,16 @@ public class FileResource extends BaseResource {
* *
* @param context Context * @param context Context
* @param id ID * @param id ID
* @param responseHandler Callback * @param callback Callback
*/ */
public static void delete(Context context, String id, JsonHttpResponseHandler responseHandler) { public static void delete(Context context, String id, HttpCallback callback) {
init(context); Request request = new Request.Builder()
.url(HttpUrl.parse(getApiUrl(context) + "/file/" + id))
client.delete(getApiUrl(context) + "/file/" + id, responseHandler); .delete()
.build();
OkHttpUtil.buildClient(context)
.newCall(request)
.enqueue(HttpCallback.buildOkHttpCallback(callback));
} }
/** /**
@ -49,34 +71,53 @@ public class FileResource extends BaseResource {
* @param context Context * @param context Context
* @param documentId Document ID * @param documentId Document ID
* @param is Input stream * @param is Input stream
* @param responseHandler Callback * @param callback Callback
* @throws Exception * @throws Exception
*/ */
public static void addSync(Context context, String documentId, InputStream is, JsonHttpResponseHandler responseHandler) throws Exception { public static void addSync(Context context, String documentId, final InputStream is, HttpCallback callback) throws Exception {
init(context); Request request = new Request.Builder()
.url(HttpUrl.parse(getApiUrl(context) + "/file"))
.put(new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("id", documentId)
.addFormDataPart("file", "file", new RequestBody() {
@Override
public MediaType contentType() {
return MediaType.parse("application/octet-stream");
}
SyncHttpClient client = new SyncHttpClient(); @Override
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); public void writeTo(BufferedSink sink) throws IOException {
trustStore.load(null, null); Source source = Okio.source(is);
MySSLSocketFactory sf = new MySSLSocketFactory(trustStore); try {
sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); sink.writeAll(source);
client.setSSLSocketFactory(sf); } finally {
client.setCookieStore(new PersistentCookieStore(context)); Util.closeQuietly(source);
client.setUserAgent(USER_AGENT); }
client.addHeader("Accept-Language", ACCEPT_LANGUAGE); }
})
.build())
.build();
Response response = OkHttpUtil.buildClient(context)
.newCall(request)
.execute();
RequestParams params = new RequestParams(); // Call the right callback
params.put("id", documentId); final String body = response.body().string();
params.put("file", is, "file", "application/octet-stream", true); if (response.isSuccessful()) {
client.put(getApiUrl(context) + "/file", params, responseHandler); try {
} callback.onSuccess(new JSONObject(body));
} catch (Exception e) {
callback.onFailure(null, e);
}
} else {
try {
callback.onFailure(new JSONObject(body), null);
} catch (Exception e) {
callback.onFailure(null, e);
}
}
/** callback.onFinish();
* Cancel pending requests.
*
* @param context Context
*/
public static void cancel(Context context) {
client.cancelRequests(context, true);
} }
} }

View File

@ -2,8 +2,12 @@ package com.sismics.docs.resource;
import android.content.Context; import android.content.Context;
import com.loopj.android.http.RequestParams; import com.sismics.docs.listener.HttpCallback;
import com.sismics.docs.listener.JsonHttpResponseHandler; import com.sismics.docs.util.OkHttpUtil;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Request;
/** /**
@ -18,15 +22,19 @@ public class ShareResource extends BaseResource {
* @param context Context * @param context Context
* @param documentId Document ID * @param documentId Document ID
* @param name Name * @param name Name
* @param responseHandler Callback * @param callback Callback
*/ */
public static void add(Context context, String documentId, String name, JsonHttpResponseHandler responseHandler) { public static void add(Context context, String documentId, String name, HttpCallback callback) {
init(context); Request request = new Request.Builder()
.url(HttpUrl.parse(getApiUrl(context) + "/share"))
RequestParams params = new RequestParams(); .put(new FormBody.Builder()
params.put("id", documentId); .add("id", documentId)
params.put("name", name); .add("name", name)
client.put(getApiUrl(context) + "/share", params, responseHandler); .build())
.build();
OkHttpUtil.buildClient(context)
.newCall(request)
.enqueue(HttpCallback.buildOkHttpCallback(callback));
} }
/** /**
@ -34,11 +42,15 @@ public class ShareResource extends BaseResource {
* *
* @param context Context * @param context Context
* @param id ID * @param id ID
* @param responseHandler Callback * @param callback Callback
*/ */
public static void delete(Context context, String id, JsonHttpResponseHandler responseHandler) { public static void delete(Context context, String id, HttpCallback callback) {
init(context); Request request = new Request.Builder()
.url(HttpUrl.parse(getApiUrl(context) + "/share/" + id))
client.delete(getApiUrl(context) + "/share/" + id, responseHandler); .delete()
.build();
OkHttpUtil.buildClient(context)
.newCall(request)
.enqueue(HttpCallback.buildOkHttpCallback(callback));
} }
} }

View File

@ -2,7 +2,11 @@ package com.sismics.docs.resource;
import android.content.Context; import android.content.Context;
import com.sismics.docs.listener.JsonHttpResponseHandler; import com.sismics.docs.listener.HttpCallback;
import com.sismics.docs.util.OkHttpUtil;
import okhttp3.HttpUrl;
import okhttp3.Request;
/** /**
@ -15,11 +19,15 @@ public class TagResource extends BaseResource {
* GET /tag/stats. * GET /tag/stats.
* *
* @param context Context * @param context Context
* @param responseHandler Callback * @param callback Callback
*/ */
public static void stats(Context context, JsonHttpResponseHandler responseHandler) { public static void stats(Context context, HttpCallback callback) {
init(context); Request request = new Request.Builder()
.url(HttpUrl.parse(getApiUrl(context) + "/tag/stats"))
client.get(getApiUrl(context) + "/tag/stats", responseHandler); .get()
.build();
OkHttpUtil.buildClient(context)
.newCall(request)
.enqueue(HttpCallback.buildOkHttpCallback(callback));
} }
} }

View File

@ -2,8 +2,12 @@ package com.sismics.docs.resource;
import android.content.Context; import android.content.Context;
import com.loopj.android.http.RequestParams; import com.sismics.docs.listener.HttpCallback;
import com.sismics.docs.listener.JsonHttpResponseHandler; import com.sismics.docs.util.OkHttpUtil;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Request;
/** /**
* Access to /user API. * Access to /user API.
@ -18,41 +22,51 @@ public class UserResource extends BaseResource {
* @param context Context * @param context Context
* @param username Username * @param username Username
* @param password Password * @param password Password
* @param responseHandler Callback * @param callback Callback
*/ */
public static void login(Context context, String username, String password, JsonHttpResponseHandler responseHandler) { public static void login(Context context, String username, String password, HttpCallback callback) {
init(context); Request request = new Request.Builder()
.url(HttpUrl.parse(getApiUrl(context) + "/user/login"))
RequestParams params = new RequestParams(); .post(new FormBody.Builder()
params.put("username", username); .add("username", username)
params.put("password", password); .add("password", password)
params.put("remember", "true"); .add("remember", "true")
client.post(getApiUrl(context) + "/user/login", params, responseHandler); .build())
.build();
OkHttpUtil.buildClient(context)
.newCall(request)
.enqueue(HttpCallback.buildOkHttpCallback(callback));
} }
/** /**
* GET /user. * GET /user.
* *
* @param context Context * @param context Context
* @param responseHandler Callback * @param callback Callback
*/ */
public static void info(Context context, JsonHttpResponseHandler responseHandler) { public static void info(Context context, HttpCallback callback) {
init(context); Request request = new Request.Builder()
.url(HttpUrl.parse(getApiUrl(context) + "/user"))
RequestParams params = new RequestParams(); .get()
client.get(getApiUrl(context) + "/user", params, responseHandler); .build();
OkHttpUtil.buildClient(context)
.newCall(request)
.enqueue(HttpCallback.buildOkHttpCallback(callback));
} }
/** /**
* POST /user/logout. * POST /user/logout.
* *
* @param context Context * @param context Context
* @param responseHandler Callback * @param callback Callback
*/ */
public static void logout(Context context, JsonHttpResponseHandler responseHandler) { public static void logout(Context context, HttpCallback callback) {
init(context); Request request = new Request.Builder()
.url(HttpUrl.parse(getApiUrl(context) + "/user/logout"))
RequestParams params = new RequestParams(); .post(new FormBody.Builder().build())
client.post(getApiUrl(context) + "/user/logout", params, responseHandler); .build();
OkHttpUtil.buildClient(context)
.newCall(request)
.enqueue(HttpCallback.buildOkHttpCallback(callback));
} }
} }

View File

@ -12,16 +12,16 @@ import android.util.Log;
import com.sismics.docs.R; import com.sismics.docs.R;
import com.sismics.docs.event.FileAddEvent; import com.sismics.docs.event.FileAddEvent;
import com.sismics.docs.listener.JsonHttpResponseHandler; import com.sismics.docs.listener.HttpCallback;
import com.sismics.docs.resource.FileResource; import com.sismics.docs.resource.FileResource;
import org.greenrobot.eventbus.EventBus;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import cz.msebera.android.httpclient.Header; import okhttp3.internal.Util;
import de.greenrobot.event.EventBus;
/** /**
* Service to upload a file to a document in the background. * Service to upload a file to a document in the background.
@ -81,17 +81,22 @@ public class FileUploadService extends IntentService {
*/ */
private void handleFileUpload(final String documentId, final Uri uri) throws Exception { private void handleFileUpload(final String documentId, final Uri uri) throws Exception {
final InputStream is = getContentResolver().openInputStream(uri); final InputStream is = getContentResolver().openInputStream(uri);
FileResource.addSync(this, documentId, is, new JsonHttpResponseHandler() { FileResource.addSync(this, documentId, is, new HttpCallback() {
@Override @Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) { public void onSuccess(JSONObject response) {
EventBus.getDefault().post(new FileAddEvent(documentId, response.optString("id"))); EventBus.getDefault().post(new FileAddEvent(documentId, response.optString("id")));
FileUploadService.this.onComplete(); FileUploadService.this.onComplete();
} }
@Override @Override
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { public void onFailure(JSONObject json, Exception e) {
FileUploadService.this.onError(); FileUploadService.this.onError();
} }
@Override
public void onFinish() {
Util.closeQuietly(is);
}
}); });
} }

View File

@ -10,7 +10,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
* @author bgamard * @author bgamard
*/ */
public class ApplicationUtil { public class ApplicationUtil {
/** /**
* Returns version name. * Returns version name.
* *

View File

@ -12,7 +12,6 @@ import com.sismics.docs.R;
* @author bgamard * @author bgamard
*/ */
public class DialogUtil { public class DialogUtil {
/** /**
* Create a dialog with an OK button. * Create a dialog with an OK button.
* *

View File

@ -0,0 +1,33 @@
package com.sismics.docs.util;
import android.app.DownloadManager;
import android.content.Context;
import android.net.Uri;
import android.os.Environment;
/**
* Utility class for network actions.
*
* @author bgamard.
*/
public class NetworkUtil {
/**
* Download a file using Android download manager.
*
* @param url URL to download
* @param fileName Destination file name
* @param title Notification title
* @param description Notification description
*/
public static void downloadFile(Context context, String url, String fileName, String title, String description) {
String authToken = PreferenceUtil.getAuthToken(context);
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
request.addRequestHeader("Cookie", "auth_token=" + authToken);
request.setTitle(title);
request.setDescription(description);
downloadManager.enqueue(request);
}
}

View File

@ -11,8 +11,6 @@ import com.squareup.picasso.Picasso;
import java.io.IOException; import java.io.IOException;
import java.net.CookieManager; import java.net.CookieManager;
import java.net.CookiePolicy; import java.net.CookiePolicy;
import java.net.HttpCookie;
import java.net.URI;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -105,10 +103,10 @@ public class OkHttpUtil {
@Override @Override
public Response intercept(Interceptor.Chain chain) throws IOException { // Override cache configuration public Response intercept(Interceptor.Chain chain) throws IOException { // Override cache configuration
final Request original = chain.request(); final Request original = chain.request();
final Request.Builder requestBuilder = original.newBuilder() return chain.proceed(original.newBuilder()
.header("Cache-Control", "max-age=" + (3600 * 24 * 365)) .header("Cache-Control", "max-age=" + (3600 * 24 * 365))
.method(original.method(), original.body()); .method(original.method(), original.body())
return chain.proceed(requestBuilder.build()); .build());
} }
}) })
.cache(getCache(context)) .cache(getCache(context))
@ -169,8 +167,6 @@ public class OkHttpUtil {
// Cookie handling // Cookie handling
PersistentCookieStore cookieStore = new PersistentCookieStore(context); PersistentCookieStore cookieStore = new PersistentCookieStore(context);
CookieManager cookieManager = new CookieManager(cookieStore, CookiePolicy.ACCEPT_ALL); CookieManager cookieManager = new CookieManager(cookieStore, CookiePolicy.ACCEPT_ALL);
cookieStore.add(URI.create(PreferenceUtil.getServerUrl(context)),
new HttpCookie("auth_token", PreferenceUtil.getAuthToken(context))); // TODO Remove me when async http is ditched
// Runtime configuration // Runtime configuration
return okHttpClient.newBuilder() return okHttpClient.newBuilder()
@ -178,11 +174,11 @@ public class OkHttpUtil {
.addNetworkInterceptor(new Interceptor() { .addNetworkInterceptor(new Interceptor() {
@Override @Override
public Response intercept(Chain chain) throws IOException { public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request(); Request original = chain.request();
return chain.proceed(originalRequest.newBuilder() return chain.proceed(original.newBuilder()
.header("User-Agent", userAgent) .header("User-Agent", userAgent)
.header("Accept-Language", acceptLanguage) .header("Accept-Language", acceptLanguage)
// TODO necessary?? .method(originalRequest.method(), originalRequest.body()) .method(original.method(), original.body())
.build()); .build());
} }
}) })

View File

@ -5,14 +5,13 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import com.loopj.android.http.PersistentCookieStore; import com.sismics.docs.resource.cookie.PersistentCookieStore;
import org.json.JSONObject; import org.json.JSONObject;
import java.net.HttpCookie;
import java.util.List; import java.util.List;
import cz.msebera.android.httpclient.cookie.Cookie;
/** /**
* Utility class on preferences. * Utility class on preferences.
* *
@ -27,6 +26,7 @@ public class PreferenceUtil {
/** /**
* Returns a preference of boolean type. * Returns a preference of boolean type.
*
* @param context Context * @param context Context
* @param key Shared preference key * @param key Shared preference key
* @return Shared preference value * @return Shared preference value
@ -38,6 +38,7 @@ public class PreferenceUtil {
/** /**
* Returns a preference of string type. * Returns a preference of string type.
*
* @param context Context * @param context Context
* @param key Shared preference key * @param key Shared preference key
* @return Shared preference value * @return Shared preference value
@ -49,6 +50,7 @@ public class PreferenceUtil {
/** /**
* Returns a preference of integer type. * Returns a preference of integer type.
*
* @param context Context * @param context Context
* @param key Shared preference key * @param key Shared preference key
* @return Shared preference value * @return Shared preference value
@ -70,6 +72,7 @@ public class PreferenceUtil {
/** /**
* Update JSON cache. * Update JSON cache.
*
* @param context Context * @param context Context
* @param key Shared preference key * @param key Shared preference key
* @param json JSON data * @param json JSON data
@ -81,6 +84,7 @@ public class PreferenceUtil {
/** /**
* Returns a JSON cache. * Returns a JSON cache.
*
* @param context Context * @param context Context
* @param key Shared preference key * @param key Shared preference key
* @return JSON data * @return JSON data
@ -97,6 +101,7 @@ public class PreferenceUtil {
/** /**
* Update server URL. * Update server URL.
*
* @param context Context * @param context Context
*/ */
public static void setServerUrl(Context context, String serverUrl) { public static void setServerUrl(Context context, String serverUrl) {
@ -106,6 +111,7 @@ public class PreferenceUtil {
/** /**
* Empty user caches. * Empty user caches.
*
* @param context Context * @param context Context
*/ */
public static void resetUserCache(Context context) { public static void resetUserCache(Context context) {
@ -119,12 +125,13 @@ public class PreferenceUtil {
/** /**
* Returns auth token cookie from shared preferences. * Returns auth token cookie from shared preferences.
*
* @return Auth token * @return Auth token
*/ */
public static String getAuthToken(Context context) { public static String getAuthToken(Context context) {
PersistentCookieStore cookieStore = new PersistentCookieStore(context); PersistentCookieStore cookieStore = new PersistentCookieStore(context);
List<Cookie> cookieList = cookieStore.getCookies(); List<HttpCookie> cookieList = cookieStore.getCookies();
for (Cookie cookie : cookieList) { for (HttpCookie cookie : cookieList) {
if (cookie.getName().equals("auth_token")) { if (cookie.getName().equals("auth_token")) {
return cookie.getValue(); return cookie.getValue();
} }
@ -135,6 +142,7 @@ public class PreferenceUtil {
/** /**
* Returns cleaned server URL. * Returns cleaned server URL.
*
* @param context Context * @param context Context
* @return Server URL * @return Server URL
*/ */

View File

@ -8,23 +8,59 @@
<CheckBox <CheckBox
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Export metadata" android:layout_margin="6dp"
android:id="@+id/checkBox" /> android:text="@string/export_metadata"
android:id="@+id/exportMetadataCheckbox" />
<CheckBox <CheckBox
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Export comments" android:layout_margin="6dp"
android:id="@+id/checkBox2" /> android:text="@string/export_comments"
android:id="@+id/exportCommentsCheckbox" />
<CheckBox <CheckBox
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Fit image to page" android:layout_margin="6dp"
android:id="@+id/checkBox3" /> android:checked="true"
android:text="@string/fit_image_to_page"
android:id="@+id/fitToPageCheckbox" />
<SeekBar <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/seekBar" /> android:layout_margin="16dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/margin"
android:layout_weight="0"/>
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="@+id/marginSeekBar"
android:progress="10"
android:max="50"/>
<TextView
android:id="@+id/marginValueText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:text="10"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:layout_weight="0"
android:text="@string/mm"/>
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -28,9 +28,7 @@
<string name="crash_toast_text">A crash occurred, a report has been sent to resolve this problem</string> <string name="crash_toast_text">A crash occurred, a report has been sent to resolve this problem</string>
<string name="created_date">Created date</string> <string name="created_date">Created date</string>
<string name="download_file">Download current file</string> <string name="download_file">Download current file</string>
<string name="downloading_file">Downloading file number %1s</string>
<string name="download_document">Download</string> <string name="download_document">Download</string>
<string name="downloading_document">Downloading document</string>
<string name="action_search">Search documents</string> <string name="action_search">Search documents</string>
<string name="all_documents">All documents</string> <string name="all_documents">All documents</string>
<string name="shared_documents">Shared documents</string> <string name="shared_documents">Shared documents</string>
@ -119,6 +117,13 @@
<string name="error_deleting_comment">Error deleting comment</string> <string name="error_deleting_comment">Error deleting comment</string>
<string name="export_pdf">Export PDF</string> <string name="export_pdf">Export PDF</string>
<string name="download">Download</string> <string name="download">Download</string>
<string name="margin">Margin</string>
<string name="fit_image_to_page">Fit image to page</string>
<string name="export_comments">Export comments</string>
<string name="export_metadata">Export metadata</string>
<string name="mm">mm</string>
<string name="download_file_title">Sismics Docs file export</string>
<string name="download_document_title">Sismics Docs document export</string>
<string name="download_pdf_title">Sismics Docs PDF export</string>
</resources> </resources>

View File

@ -28,7 +28,7 @@
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId> <artifactId>hibernate-c3p0</artifactId>
</dependency> </dependency>
<!-- Other external dependencies --> <!-- Other external dependencies -->

View File

@ -1,21 +1,11 @@
package com.sismics.util.jpa; package com.sismics.util.jpa;
import com.google.common.base.Strings; import java.io.File;
import com.google.common.io.CharStreams; import java.io.FilenameFilter;
import com.sismics.docs.core.util.ConfigUtil; import java.io.IOException;
import com.sismics.util.ResourceUtil; import java.io.InputStream;
import org.hibernate.HibernateException; import java.io.InputStreamReader;
import org.hibernate.JDBCException; import java.io.Writer;
import org.hibernate.engine.jdbc.internal.FormatStyle;
import org.hibernate.engine.jdbc.internal.Formatter;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tool.hbm2ddl.ConnectionHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@ -26,6 +16,22 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.internal.FormatStyle;
import org.hibernate.engine.jdbc.internal.Formatter;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.service.ServiceRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Strings;
import com.google.common.io.CharStreams;
import com.sismics.docs.core.util.ConfigUtil;
import com.sismics.util.ResourceUtil;
/** /**
* A helper to update the database incrementally. * A helper to update the database incrementally.
* *
@ -37,10 +43,10 @@ public abstract class DbOpenHelper {
*/ */
private static final Logger log = LoggerFactory.getLogger(DbOpenHelper.class); private static final Logger log = LoggerFactory.getLogger(DbOpenHelper.class);
private final ConnectionHelper connectionHelper;
private final SqlStatementLogger sqlStatementLogger; private final SqlStatementLogger sqlStatementLogger;
private final JdbcConnectionAccess jdbcConnectionAccess;
private final List<Exception> exceptions = new ArrayList<Exception>(); private final List<Exception> exceptions = new ArrayList<Exception>();
private Formatter formatter; private Formatter formatter;
@ -51,9 +57,8 @@ public abstract class DbOpenHelper {
public DbOpenHelper(ServiceRegistry serviceRegistry) throws HibernateException { public DbOpenHelper(ServiceRegistry serviceRegistry) throws HibernateException {
final JdbcServices jdbcServices = serviceRegistry.getService(JdbcServices.class); final JdbcServices jdbcServices = serviceRegistry.getService(JdbcServices.class);
connectionHelper = new SuppliedConnectionProviderConnectionHelper(jdbcServices.getConnectionProvider());
sqlStatementLogger = jdbcServices.getSqlStatementLogger(); sqlStatementLogger = jdbcServices.getSqlStatementLogger();
jdbcConnectionAccess = jdbcServices.getBootstrapJdbcConnectionAccess();
formatter = (sqlStatementLogger.isFormat() ? FormatStyle.DDL : FormatStyle.NONE).getFormatter(); formatter = (sqlStatementLogger.isFormat() ? FormatStyle.DDL : FormatStyle.NONE).getFormatter();
} }
@ -67,8 +72,7 @@ public abstract class DbOpenHelper {
try { try {
try { try {
connectionHelper.prepare(true); connection = jdbcConnectionAccess.obtainConnection();
connection = connectionHelper.getConnection();
} catch (SQLException sqle) { } catch (SQLException sqle) {
exceptions.add(sqle); exceptions.add(sqle);
log.error("Unable to get database metadata", sqle); log.error("Unable to get database metadata", sqle);
@ -120,7 +124,7 @@ public abstract class DbOpenHelper {
stmt.close(); stmt.close();
stmt = null; stmt = null;
} }
connectionHelper.release(); jdbcConnectionAccess.releaseConnection(connection);
} catch (Exception e) { } catch (Exception e) {
exceptions.add(e); exceptions.add(e);
log.error("Unable to close connection", e); log.error("Unable to close connection", e);

View File

@ -11,10 +11,10 @@ import java.util.Properties;
import javax.persistence.EntityManagerFactory; import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence; import javax.persistence.Persistence;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -36,7 +36,7 @@ public final class EMF {
Environment.verifyProperties(properties); Environment.verifyProperties(properties);
ConfigurationHelper.resolvePlaceHolders(properties); ConfigurationHelper.resolvePlaceHolders(properties);
ServiceRegistry reg = new ServiceRegistryBuilder().applySettings(properties).buildServiceRegistry(); ServiceRegistry reg = new StandardServiceRegistryBuilder().applySettings(properties).build();
DbOpenHelper openHelper = new DbOpenHelper(reg) { DbOpenHelper openHelper = new DbOpenHelper(reg) {
@ -85,12 +85,16 @@ public final class EMF {
String dbFile = dbDirectory.resolve("docs").toAbsolutePath().toString(); String dbFile = dbDirectory.resolve("docs").toAbsolutePath().toString();
props.put("hibernate.connection.url", "jdbc:h2:file:" + dbFile + ";CACHE_SIZE=65536"); props.put("hibernate.connection.url", "jdbc:h2:file:" + dbFile + ";CACHE_SIZE=65536");
props.put("hibernate.connection.username", "sa"); props.put("hibernate.connection.username", "sa");
props.put("hibernate.hbm2ddl.auto", "none"); props.put("hibernate.hbm2ddl.auto", "");
props.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect"); props.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
props.put("hibernate.show_sql", "false"); props.put("hibernate.show_sql", "false");
props.put("hibernate.format_sql", "false"); props.put("hibernate.format_sql", "false");
props.put("hibernate.max_fetch_depth", "5"); props.put("hibernate.max_fetch_depth", "5");
props.put("hibernate.cache.use_second_level_cache", "false"); props.put("hibernate.cache.use_second_level_cache", "false");
props.put("hibernate.c3p0.min_size", "1");
props.put("hibernate.c3p0.max_size", "10");
props.put("hibernate.c3p0.timeout", "0");
props.put("hibernate.c3p0.max_statements", "0");
return props; return props;
} }

View File

@ -1,108 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package com.sismics.util.jpa;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.ServiceRegistryBuilder;
import org.hibernate.service.internal.StandardServiceRegistryImpl;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.tool.hbm2ddl.ConnectionHelper;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* A {@link ConnectionHelper} implementation based on an internally
* built and managed {@link ConnectionProvider}.
*
* @author Steve Ebersole
*/
class ManagedProviderConnectionHelper implements ConnectionHelper {
private Properties cfgProperties;
private StandardServiceRegistryImpl serviceRegistry;
private Connection connection;
public ManagedProviderConnectionHelper(Properties cfgProperties) {
this.cfgProperties = cfgProperties;
}
@Override
public void prepare(boolean needsAutoCommit) throws SQLException {
serviceRegistry = createServiceRegistry(cfgProperties);
connection = serviceRegistry.getService(ConnectionProvider.class).getConnection();
if (needsAutoCommit && !connection.getAutoCommit()) {
connection.commit();
connection.setAutoCommit(true);
}
}
private static StandardServiceRegistryImpl createServiceRegistry(Properties properties) {
Environment.verifyProperties(properties);
ConfigurationHelper.resolvePlaceHolders(properties);
return (StandardServiceRegistryImpl) new ServiceRegistryBuilder().applySettings(properties).buildServiceRegistry();
}
@Override
public Connection getConnection() throws SQLException {
return connection;
}
@Override
public void release() throws SQLException {
try {
releaseConnection();
} finally {
releaseServiceRegistry();
}
}
private void releaseConnection() throws SQLException {
if (connection != null) {
try {
new SqlExceptionHelper().logAndClearWarnings(connection);
} finally {
try {
serviceRegistry.getService(ConnectionProvider.class).closeConnection(connection);
} finally {
connection = null;
}
}
}
}
private void releaseServiceRegistry() {
if (serviceRegistry != null) {
try {
serviceRegistry.destroy();
} finally {
serviceRegistry = null;
}
}
}
}

View File

@ -1,28 +0,0 @@
package com.sismics.util.jpa;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.ejb.HibernateEntityManagerFactory;
/**
* Hibernate session utilities.
*
* @author jtremeaux
*/
public final class SessionUtil {
/**
* Private constructor.
*/
private SessionUtil() {
}
/**
* Returns an instance of the current session.
*
* @return Instance of the current session
*/
public static Session getCurrentSession() {
SessionFactory sessionFactory = ((HibernateEntityManagerFactory) EMF.get()).getSessionFactory();
return sessionFactory.getCurrentSession();
}
}

View File

@ -1,84 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package com.sismics.util.jpa;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.tool.hbm2ddl.ConnectionHelper;
import java.sql.Connection;
import java.sql.SQLException;
/**
* A {@link ConnectionHelper} implementation based on a provided
* {@link ConnectionProvider}. Essentially, ensures that the connection
* gets cleaned up, but that the provider itself remains usable since it
* was externally provided to us.
*
* @author Steve Ebersole
*/
class SuppliedConnectionProviderConnectionHelper implements ConnectionHelper {
private ConnectionProvider provider;
private Connection connection;
private boolean toggleAutoCommit;
public SuppliedConnectionProviderConnectionHelper(ConnectionProvider provider) {
this.provider = provider;
}
@Override
public void prepare(boolean needsAutoCommit) throws SQLException {
connection = provider.getConnection();
toggleAutoCommit = needsAutoCommit && !connection.getAutoCommit();
if ( toggleAutoCommit ) {
try {
connection.commit();
}
catch( Throwable ignore ) {
// might happen with a managed connection
}
connection.setAutoCommit( true );
}
}
@Override
public Connection getConnection() throws SQLException {
return connection;
}
@Override
public void release() throws SQLException {
// we only release the connection
if ( connection != null ) {
new SqlExceptionHelper().logAndClearWarnings( connection );
if ( toggleAutoCommit ) {
connection.setAutoCommit( false );
}
provider.closeConnection( connection );
connection = null;
}
}
}

View File

@ -3,7 +3,7 @@ package com.sismics.docs.core.dao.jpa;
import com.sismics.docs.BaseTransactionalTest; import com.sismics.docs.BaseTransactionalTest;
import com.sismics.docs.core.model.jpa.User; import com.sismics.docs.core.model.jpa.User;
import com.sismics.docs.core.util.TransactionUtil; import com.sismics.docs.core.util.TransactionUtil;
import junit.framework.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
/** /**

View File

@ -5,8 +5,7 @@ import java.io.InputStream;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.CipherInputStream; import javax.crypto.CipherInputStream;
import junit.framework.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import com.google.common.base.Strings; import com.google.common.base.Strings;

View File

@ -11,7 +11,7 @@ import com.google.common.io.Resources;
import com.sismics.docs.core.model.jpa.File; import com.sismics.docs.core.model.jpa.File;
import com.sismics.util.mime.MimeType; import com.sismics.util.mime.MimeType;
import junit.framework.Assert; import org.junit.Assert;
/** /**
* Test of the file entity utilities. * Test of the file entity utilities.

View File

@ -1,6 +1,6 @@
package com.sismics.util; package com.sismics.util;
import junit.framework.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
/** /**

View File

@ -1,6 +1,6 @@
package com.sismics.util; package com.sismics.util;
import junit.framework.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
/** /**

View File

@ -1,6 +1,6 @@
package com.sismics.util; package com.sismics.util;
import junit.framework.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import java.util.List; import java.util.List;

View File

@ -2,9 +2,13 @@ hibernate.connection.driver_class=org.h2.Driver
hibernate.connection.url=jdbc:h2:mem:docs hibernate.connection.url=jdbc:h2:mem:docs
hibernate.connection.username=sa hibernate.connection.username=sa
hibernate.connection.password= hibernate.connection.password=
hibernate.hbm2ddl.auto=none hibernate.hbm2ddl.auto=
hibernate.dialect=org.hibernate.dialect.HSQLDialect hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.show_sql=true hibernate.show_sql=true
hibernate.format_sql=false hibernate.format_sql=false
hibernate.max_fetch_depth=5 hibernate.max_fetch_depth=5
hibernate.cache.use_second_level_cache=false hibernate.cache.use_second_level_cache=false
hibernate.c3p0.min_size=1
hibernate.c3p0.max_size=10
hibernate.c3p0.timeout=0
hibernate.c3p0.max_statements=0

View File

@ -20,20 +20,20 @@
<commons-lang.commons-lang.version>2.6</commons-lang.commons-lang.version> <commons-lang.commons-lang.version>2.6</commons-lang.commons-lang.version>
<commons-io.commons-io.version>2.4</commons-io.commons-io.version> <commons-io.commons-io.version>2.4</commons-io.commons-io.version>
<commons-dbcp.version>1.4</commons-dbcp.version> <commons-dbcp.version>1.4</commons-dbcp.version>
<com.google.guava.guava.version>18.0</com.google.guava.guava.version> <com.google.guava.guava.version>19.0</com.google.guava.guava.version>
<log4j.log4j.version>1.2.16</log4j.log4j.version> <log4j.log4j.version>1.2.16</log4j.log4j.version>
<org.slf4j.version>1.6.4</org.slf4j.version> <org.slf4j.version>1.6.4</org.slf4j.version>
<org.slf4j.jcl-over-slf4j.version>1.6.6</org.slf4j.jcl-over-slf4j.version> <org.slf4j.jcl-over-slf4j.version>1.6.6</org.slf4j.jcl-over-slf4j.version>
<junit.junit.version>4.7</junit.junit.version> <junit.junit.version>4.12</junit.junit.version>
<com.h2database.h2.version>1.4.190</com.h2database.h2.version> <com.h2database.h2.version>1.4.191</com.h2database.h2.version>
<org.glassfish.jersey.version>2.22.1</org.glassfish.jersey.version> <org.glassfish.jersey.version>2.22.1</org.glassfish.jersey.version>
<org.mindrot.jbcrypt>0.3m</org.mindrot.jbcrypt> <org.mindrot.jbcrypt>0.3m</org.mindrot.jbcrypt>
<org.apache.lucene.version>4.2.0</org.apache.lucene.version> <org.apache.lucene.version>4.2.0</org.apache.lucene.version>
<org.imgscalr.imgscalr-lib.version>4.2</org.imgscalr.imgscalr-lib.version> <org.imgscalr.imgscalr-lib.version>4.2</org.imgscalr.imgscalr-lib.version>
<org.apache.pdfbox.pdfbox.version>2.0.0-RC2</org.apache.pdfbox.pdfbox.version> <org.apache.pdfbox.pdfbox.version>2.0.0-RC3</org.apache.pdfbox.pdfbox.version>
<org.bouncycastle.bcprov-jdk15on.version>1.53</org.bouncycastle.bcprov-jdk15on.version> <org.bouncycastle.bcprov-jdk15on.version>1.54</org.bouncycastle.bcprov-jdk15on.version>
<joda-time.joda-time.version>2.9.1</joda-time.joda-time.version> <joda-time.joda-time.version>2.9.1</joda-time.joda-time.version>
<org.hibernate.hibernate.version>4.1.0.Final</org.hibernate.hibernate.version> <org.hibernate.hibernate.version>5.0.7.Final</org.hibernate.hibernate.version>
<javax.servlet.javax.servlet-api.version>3.1.0</javax.servlet.javax.servlet-api.version> <javax.servlet.javax.servlet-api.version>3.1.0</javax.servlet.javax.servlet-api.version>
<fr.opensagres.xdocreport.version>1.0.5</fr.opensagres.xdocreport.version> <fr.opensagres.xdocreport.version>1.0.5</fr.opensagres.xdocreport.version>
<net.java.dev.jna.jna.version>4.2.1</net.java.dev.jna.jna.version> <net.java.dev.jna.jna.version>4.2.1</net.java.dev.jna.jna.version>
@ -48,11 +48,10 @@
<!-- Plugins version --> <!-- Plugins version -->
<org.apache.maven.plugins.maven-antrun-plugin.version>1.8</org.apache.maven.plugins.maven-antrun-plugin.version> <org.apache.maven.plugins.maven-antrun-plugin.version>1.8</org.apache.maven.plugins.maven-antrun-plugin.version>
<org.apache.maven.plugins.maven-dependency-plugin.version>2.10</org.apache.maven.plugins.maven-dependency-plugin.version> <org.apache.maven.plugins.maven-dependency-plugin.version>2.10</org.apache.maven.plugins.maven-dependency-plugin.version>
<org.apache.maven.plugins.maven-jar-plugin.version>2.4</org.apache.maven.plugins.maven-jar-plugin.version> <org.apache.maven.plugins.maven-jar-plugin.version>2.6</org.apache.maven.plugins.maven-jar-plugin.version>
<org.apache.maven.plugins.maven-release-plugin.version>2.5.2</org.apache.maven.plugins.maven-release-plugin.version>
<org.apache.maven.plugins.maven-resources-plugin.version>2.7</org.apache.maven.plugins.maven-resources-plugin.version> <org.apache.maven.plugins.maven-resources-plugin.version>2.7</org.apache.maven.plugins.maven-resources-plugin.version>
<org.apache.maven.plugins.maven-war-plugin.version>2.6</org.apache.maven.plugins.maven-war-plugin.version> <org.apache.maven.plugins.maven-war-plugin.version>2.6</org.apache.maven.plugins.maven-war-plugin.version>
<org.apache.maven.plugins.maven-surefire-plugin.version>2.18.1</org.apache.maven.plugins.maven-surefire-plugin.version> <org.apache.maven.plugins.maven-surefire-plugin.version>2.19.1</org.apache.maven.plugins.maven-surefire-plugin.version>
<org.eclipse.jetty.jetty-maven-plugin.version>9.2.13.v20150730</org.eclipse.jetty.jetty-maven-plugin.version> <org.eclipse.jetty.jetty-maven-plugin.version>9.2.13.v20150730</org.eclipse.jetty.jetty-maven-plugin.version>
</properties> </properties>
@ -306,7 +305,7 @@
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId> <artifactId>hibernate-c3p0</artifactId>
<version>${org.hibernate.hibernate.version}</version> <version>${org.hibernate.hibernate.version}</version>
</dependency> </dependency>

View File

@ -17,7 +17,7 @@ import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import junit.framework.Assert; import org.junit.Assert;
import org.glassfish.jersey.client.ClientResponse; import org.glassfish.jersey.client.ClientResponse;
import org.glassfish.jersey.media.multipart.FormDataMultiPart; import org.glassfish.jersey.media.multipart.FormDataMultiPart;

View File

@ -2,7 +2,7 @@ package com.sismics.docs.rest.util;
import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ClientException;
import com.sismics.rest.util.ValidationUtil; import com.sismics.rest.util.ValidationUtil;
import junit.framework.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
/** /**

View File

@ -2,9 +2,13 @@ hibernate.connection.driver_class=org.h2.Driver
hibernate.connection.url=jdbc:h2:mem:docs hibernate.connection.url=jdbc:h2:mem:docs
hibernate.connection.username=sa hibernate.connection.username=sa
hibernate.connection.password= hibernate.connection.password=
hibernate.hbm2ddl.auto=none hibernate.hbm2ddl.auto=
hibernate.dialect=org.hibernate.dialect.HSQLDialect hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.show_sql=false hibernate.show_sql=false
hibernate.format_sql=false hibernate.format_sql=false
hibernate.max_fetch_depth=5 hibernate.max_fetch_depth=5
hibernate.cache.use_second_level_cache=false hibernate.cache.use_second_level_cache=false
hibernate.c3p0.min_size=1
hibernate.c3p0.max_size=10
hibernate.c3p0.timeout=0
hibernate.c3p0.max_statements=0

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ import javax.ws.rs.core.Form;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import junit.framework.Assert; import org.junit.Assert;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.junit.Test; import org.junit.Test;

View File

@ -2,9 +2,13 @@ hibernate.connection.driver_class=org.h2.Driver
hibernate.connection.url=jdbc:h2:mem:docs hibernate.connection.url=jdbc:h2:mem:docs
hibernate.connection.username=sa hibernate.connection.username=sa
hibernate.connection.password= hibernate.connection.password=
hibernate.hbm2ddl.auto=none hibernate.hbm2ddl.auto=
hibernate.dialect=org.hibernate.dialect.HSQLDialect hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.show_sql=true hibernate.show_sql=true
hibernate.format_sql=false hibernate.format_sql=false
hibernate.max_fetch_depth=5 hibernate.max_fetch_depth=5
hibernate.cache.use_second_level_cache=false hibernate.cache.use_second_level_cache=false
hibernate.c3p0.min_size=1
hibernate.c3p0.max_size=10
hibernate.c3p0.timeout=0
hibernate.c3p0.max_statements=0