├── .gitattributes
├── .gitignore
├── .travis.yml
├── COPYING
├── README.md
├── pom.xml
├── reader-agent
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── sismics
│ │ ├── reader
│ │ └── agent
│ │ │ ├── ReaderAgent.java
│ │ │ ├── deployer
│ │ │ ├── DeploymentStatus.java
│ │ │ ├── DeploymentStatusListener.java
│ │ │ └── ReaderDeployer.java
│ │ │ ├── model
│ │ │ └── Setting.java
│ │ │ └── ui
│ │ │ ├── AgentFrame.java
│ │ │ ├── SettingPanel.java
│ │ │ ├── StatusPanel.java
│ │ │ └── TrayController.java
│ │ └── util
│ │ ├── EnvironmentUtil.java
│ │ └── MessageUtil.java
│ └── resources
│ ├── images
│ ├── reader-started-16.png
│ └── reader-stopped-16.png
│ ├── messages.properties
│ └── messages_fr.properties
├── reader-android
├── .gitignore
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── libs
│ │ ├── android-query.0.26.7.jar
│ │ └── drag-sort-listview-0.6.1-SNAPSHOT-AAR.aar
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── sismics
│ │ │ ├── android
│ │ │ ├── Log.java
│ │ │ └── util
│ │ │ │ └── DialogUtil.java
│ │ │ ├── parallaxscroll
│ │ │ ├── ParallaxScrollView.java
│ │ │ └── ParallaxedView.java
│ │ │ └── reader
│ │ │ ├── MainApplication.java
│ │ │ ├── activity
│ │ │ ├── ArticleActivity.java
│ │ │ ├── CategoriesActivity.java
│ │ │ ├── LicenseActivity.java
│ │ │ ├── LoginActivity.java
│ │ │ ├── MainActivity.java
│ │ │ └── SettingsActivity.java
│ │ │ ├── constant
│ │ │ └── Constants.java
│ │ │ ├── fragment
│ │ │ ├── AddSubscriptionDialogFragment.java
│ │ │ ├── ArticleFragment.java
│ │ │ ├── ArticlesDefaultFragment.java
│ │ │ ├── ArticlesFragment.java
│ │ │ ├── NavigationFragment.java
│ │ │ └── SettingsFragment.java
│ │ │ ├── listener
│ │ │ ├── ArticlesHelperListener.java
│ │ │ └── CallbackListener.java
│ │ │ ├── model
│ │ │ └── application
│ │ │ │ └── ApplicationContext.java
│ │ │ ├── provider
│ │ │ └── RecentSuggestionsProvider.java
│ │ │ ├── resource
│ │ │ ├── ArticleResource.java
│ │ │ ├── BaseResource.java
│ │ │ ├── CategoryResource.java
│ │ │ ├── StarredResource.java
│ │ │ ├── SubscriptionResource.java
│ │ │ └── UserResource.java
│ │ │ ├── ui
│ │ │ ├── adapter
│ │ │ │ ├── ArticlesAdapter.java
│ │ │ │ ├── ArticlesPagerAdapter.java
│ │ │ │ ├── CategoryAdapter.java
│ │ │ │ ├── SharedArticlesAdapterHelper.java
│ │ │ │ ├── SubscriptionAdapter.java
│ │ │ │ └── SubscriptionItem.java
│ │ │ ├── form
│ │ │ │ ├── Validable.java
│ │ │ │ ├── Validator.java
│ │ │ │ └── validator
│ │ │ │ │ ├── Alphanumeric.java
│ │ │ │ │ ├── Email.java
│ │ │ │ │ ├── Length.java
│ │ │ │ │ ├── Required.java
│ │ │ │ │ └── ValidatorType.java
│ │ │ └── widget
│ │ │ │ ├── ArticleScrollView.java
│ │ │ │ └── ArticlesSwipeRefreshLayout.java
│ │ │ └── util
│ │ │ ├── ApplicationUtil.java
│ │ │ └── PreferenceUtil.java
│ │ └── res
│ │ ├── anim
│ │ └── rssman.xml
│ │ ├── drawable-hdpi
│ │ ├── character.png
│ │ ├── character_happy.png
│ │ ├── character_sad.png
│ │ ├── ic_action_about.png
│ │ ├── ic_action_accept.png
│ │ ├── ic_action_collection.png
│ │ ├── ic_action_collection_inverse.png
│ │ ├── ic_action_collection_new.png
│ │ ├── ic_action_important.png
│ │ ├── ic_action_important_inverse.png
│ │ ├── ic_action_new_inverse.png
│ │ ├── ic_action_not_important.png
│ │ ├── ic_action_not_important_inverse.png
│ │ ├── ic_action_read.png
│ │ ├── ic_action_read_inverse.png
│ │ ├── ic_action_settings.png
│ │ ├── ic_action_share_inverse.png
│ │ ├── ic_action_sort_by_size.png
│ │ ├── ic_action_unread.png
│ │ ├── ic_action_unread_inverse.png
│ │ ├── ic_drag.9.png
│ │ ├── ic_menu_moreoverflow_card_inverse_normal.png
│ │ ├── ic_menu_moreoverflow_card_inverse_pressed.png
│ │ ├── list_activated_holo.9.png
│ │ └── list_background_holo.9.png
│ │ ├── drawable-sw600dp-hdpi
│ │ ├── list_activated_holo.9.png
│ │ └── list_background_holo.9.png
│ │ ├── drawable-sw600dp-xhdpi
│ │ ├── list_activated_holo.9.png
│ │ └── list_background_holo.9.png
│ │ ├── drawable-xhdpi
│ │ ├── character.png
│ │ ├── character_happy.png
│ │ ├── character_sad.png
│ │ ├── ic_action_about.png
│ │ ├── ic_action_accept.png
│ │ ├── ic_action_collection.png
│ │ ├── ic_action_collection_inverse.png
│ │ ├── ic_action_collection_new.png
│ │ ├── ic_action_important.png
│ │ ├── ic_action_important_inverse.png
│ │ ├── ic_action_new_inverse.png
│ │ ├── ic_action_not_important.png
│ │ ├── ic_action_not_important_inverse.png
│ │ ├── ic_action_read.png
│ │ ├── ic_action_read_inverse.png
│ │ ├── ic_action_settings.png
│ │ ├── ic_action_share_inverse.png
│ │ ├── ic_action_sort_by_size.png
│ │ ├── ic_action_unread.png
│ │ ├── ic_action_unread_inverse.png
│ │ ├── ic_drag.9.png
│ │ ├── ic_launcher.png
│ │ ├── ic_menu_moreoverflow_card_inverse_normal.png
│ │ ├── ic_menu_moreoverflow_card_inverse_pressed.png
│ │ ├── list_activated_holo.9.png
│ │ └── list_background_holo.9.png
│ │ ├── drawable-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── drawable-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── drawable
│ │ ├── article_title_background.xml
│ │ ├── drawer_list_item_collection.xml
│ │ ├── drawer_list_item_important.xml
│ │ ├── drawer_list_item_read.xml
│ │ ├── drawer_list_item_text_color.xml
│ │ ├── drawer_list_item_unread.xml
│ │ ├── list_item_activated_background.xml
│ │ └── overflow_menu.xml
│ │ ├── layout-sw600dp
│ │ ├── article_activity.xml
│ │ ├── article_item.xml
│ │ └── main_activity.xml
│ │ ├── layout
│ │ ├── actionbar_indeterminate_progress.xml
│ │ ├── add_subscription_dialog_fragment.xml
│ │ ├── article_activity.xml
│ │ ├── article_fragment.xml
│ │ ├── article_item.xml
│ │ ├── articles_fragment.xml
│ │ ├── categories_activity.xml
│ │ ├── drawer_list_item_category.xml
│ │ ├── drawer_list_item_header.xml
│ │ ├── drawer_list_item_subscription.xml
│ │ ├── license_activity.xml
│ │ ├── login_activity.xml
│ │ ├── main_activity.xml
│ │ └── manage_list_item_category.xml
│ │ ├── menu
│ │ ├── article_activity.xml
│ │ ├── categories_activity.xml
│ │ ├── category_overflow_menu.xml
│ │ ├── context_articles.xml
│ │ └── main.xml
│ │ ├── values-de
│ │ ├── arrays.xml
│ │ └── strings.xml
│ │ ├── values-sw600dp
│ │ └── dimens.xml
│ │ ├── values-w720dp
│ │ └── dimens.xml
│ │ ├── values
│ │ ├── arrays.xml
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ │ └── xml
│ │ ├── preferences.xml
│ │ └── searchable.xml
├── build.gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── lint.xml
└── settings.gradle
├── reader-core
├── pom.xml
└── src
│ ├── demo
│ └── resources
│ │ └── db
│ │ └── update
│ │ └── dbupdate-000-2.sql
│ ├── dev
│ └── resources
│ │ └── db
│ │ └── update
│ │ ├── dbupdate-000-1-web.sql
│ │ └── dbupdate-000-2-test.sql
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── sismics
│ │ │ ├── reader
│ │ │ └── core
│ │ │ │ ├── constant
│ │ │ │ ├── ConfigType.java
│ │ │ │ └── Constants.java
│ │ │ │ ├── dao
│ │ │ │ ├── file
│ │ │ │ │ ├── html
│ │ │ │ │ │ ├── FaviconDownloader.java
│ │ │ │ │ │ ├── FaviconExtractor.java
│ │ │ │ │ │ ├── FeedChooserStrategy.java
│ │ │ │ │ │ └── RssExtractor.java
│ │ │ │ │ ├── json
│ │ │ │ │ │ ├── StarredArticleImportedEvent.java
│ │ │ │ │ │ ├── StarredArticleImportedListener.java
│ │ │ │ │ │ └── StarredReader.java
│ │ │ │ │ ├── opml
│ │ │ │ │ │ ├── OpmlFlattener.java
│ │ │ │ │ │ ├── OpmlReader.java
│ │ │ │ │ │ └── Outline.java
│ │ │ │ │ └── rss
│ │ │ │ │ │ ├── AtomArticleCommentUrlGuesserStrategy.java
│ │ │ │ │ │ ├── AtomArticleUrlGuesserStrategy.java
│ │ │ │ │ │ ├── AtomLink.java
│ │ │ │ │ │ ├── AtomUrlGuesserStrategy.java
│ │ │ │ │ │ ├── GuidFixer.java
│ │ │ │ │ │ ├── RssReader.java
│ │ │ │ │ │ └── XmlReader.java
│ │ │ │ ├── jpa
│ │ │ │ │ ├── ArticleDao.java
│ │ │ │ │ ├── AuthenticationTokenDao.java
│ │ │ │ │ ├── CategoryDao.java
│ │ │ │ │ ├── ConfigDao.java
│ │ │ │ │ ├── FeedDao.java
│ │ │ │ │ ├── FeedSubscriptionDao.java
│ │ │ │ │ ├── FeedSynchronizationDao.java
│ │ │ │ │ ├── JobDao.java
│ │ │ │ │ ├── JobEventDao.java
│ │ │ │ │ ├── LocaleDao.java
│ │ │ │ │ ├── RoleBaseFunctionDao.java
│ │ │ │ │ ├── UserArticleDao.java
│ │ │ │ │ ├── UserDao.java
│ │ │ │ │ ├── criteria
│ │ │ │ │ │ ├── ArticleCriteria.java
│ │ │ │ │ │ ├── FeedCriteria.java
│ │ │ │ │ │ ├── FeedSubscriptionCriteria.java
│ │ │ │ │ │ ├── JobCriteria.java
│ │ │ │ │ │ ├── JobEventCriteria.java
│ │ │ │ │ │ ├── UserArticleCriteria.java
│ │ │ │ │ │ └── UserCriteria.java
│ │ │ │ │ ├── dto
│ │ │ │ │ │ ├── ArticleDto.java
│ │ │ │ │ │ ├── FeedDto.java
│ │ │ │ │ │ ├── FeedSubscriptionDto.java
│ │ │ │ │ │ ├── JobDto.java
│ │ │ │ │ │ ├── JobEventDto.java
│ │ │ │ │ │ ├── UserArticleDto.java
│ │ │ │ │ │ └── UserDto.java
│ │ │ │ │ └── mapper
│ │ │ │ │ │ ├── ArticleMapper.java
│ │ │ │ │ │ ├── FeedMapper.java
│ │ │ │ │ │ ├── FeedSubscriptionMapper.java
│ │ │ │ │ │ ├── JobEventMapper.java
│ │ │ │ │ │ ├── JobMapper.java
│ │ │ │ │ │ ├── UserArticleMapper.java
│ │ │ │ │ │ └── UserMapper.java
│ │ │ │ └── lucene
│ │ │ │ │ ├── ArticleDao.java
│ │ │ │ │ └── ReaderStandardAnalyzer.java
│ │ │ │ ├── event
│ │ │ │ ├── ArticleCreatedAsyncEvent.java
│ │ │ │ ├── ArticleDeletedAsyncEvent.java
│ │ │ │ ├── ArticleUpdatedAsyncEvent.java
│ │ │ │ ├── FaviconUpdateRequestedEvent.java
│ │ │ │ ├── PasswordChangedEvent.java
│ │ │ │ ├── RebuildIndexAsyncEvent.java
│ │ │ │ ├── SubscriptionImportedEvent.java
│ │ │ │ └── UserCreatedEvent.java
│ │ │ │ ├── listener
│ │ │ │ ├── async
│ │ │ │ │ ├── ArticleCreatedAsyncListener.java
│ │ │ │ │ ├── ArticleDeletedAsyncListener.java
│ │ │ │ │ ├── ArticleUpdatedAsyncListener.java
│ │ │ │ │ ├── FaviconUpdateRequestedAsyncListener.java
│ │ │ │ │ ├── RebuildIndexAsyncListener.java
│ │ │ │ │ └── SubscriptionImportAsyncListener.java
│ │ │ │ └── sync
│ │ │ │ │ └── DeadEventListener.java
│ │ │ │ ├── model
│ │ │ │ ├── context
│ │ │ │ │ └── AppContext.java
│ │ │ │ └── jpa
│ │ │ │ │ ├── Article.java
│ │ │ │ │ ├── AuthenticationToken.java
│ │ │ │ │ ├── BaseFunction.java
│ │ │ │ │ ├── Category.java
│ │ │ │ │ ├── Config.java
│ │ │ │ │ ├── Feed.java
│ │ │ │ │ ├── FeedSubscription.java
│ │ │ │ │ ├── FeedSynchronization.java
│ │ │ │ │ ├── Job.java
│ │ │ │ │ ├── JobEvent.java
│ │ │ │ │ ├── Locale.java
│ │ │ │ │ ├── Role.java
│ │ │ │ │ ├── RoleBaseFunction.java
│ │ │ │ │ ├── User.java
│ │ │ │ │ └── UserArticle.java
│ │ │ │ ├── service
│ │ │ │ ├── FeedService.java
│ │ │ │ └── IndexingService.java
│ │ │ │ └── util
│ │ │ │ ├── ConfigUtil.java
│ │ │ │ ├── DirectoryUtil.java
│ │ │ │ ├── EntityManagerUtil.java
│ │ │ │ ├── LuceneUtil.java
│ │ │ │ ├── StreamUtil.java
│ │ │ │ ├── TransactionUtil.java
│ │ │ │ ├── UserUtil.java
│ │ │ │ ├── http
│ │ │ │ └── ReaderHttpClient.java
│ │ │ │ ├── jpa
│ │ │ │ ├── PaginatedList.java
│ │ │ │ ├── PaginatedLists.java
│ │ │ │ └── SortCriteria.java
│ │ │ │ └── sanitizer
│ │ │ │ ├── ArticleSanitizer.java
│ │ │ │ └── TextSanitizer.java
│ │ │ └── util
│ │ │ ├── AdblockUtil.java
│ │ │ ├── DateUtil.java
│ │ │ ├── EnvironmentUtil.java
│ │ │ ├── HttpUtil.java
│ │ │ ├── JsonValidationUtil.java
│ │ │ ├── LocaleUtil.java
│ │ │ ├── MessageUtil.java
│ │ │ ├── NetworkUtil.java
│ │ │ ├── ResourceUtil.java
│ │ │ ├── UrlUtil.java
│ │ │ ├── adblock
│ │ │ ├── Helper.java
│ │ │ ├── JSEngine.java
│ │ │ ├── Subscription.java
│ │ │ └── SubscriptionParser.java
│ │ │ ├── cert
│ │ │ ├── CertUtil.java
│ │ │ └── TrustAllManager.java
│ │ │ ├── context
│ │ │ └── ThreadLocalContext.java
│ │ │ ├── jpa
│ │ │ ├── BaseDao.java
│ │ │ ├── DbOpenHelper.java
│ │ │ ├── DialectUtil.java
│ │ │ ├── EMF.java
│ │ │ ├── ManagedProvidedConnectionHelper.java
│ │ │ ├── QueryParam.java
│ │ │ ├── ResultMapper.java
│ │ │ ├── SessionUtil.java
│ │ │ ├── SuppliedConnectionProviderConnectionHelper.java
│ │ │ └── filter
│ │ │ │ ├── FilterColumn.java
│ │ │ │ └── FilterCriteria.java
│ │ │ ├── log4j
│ │ │ ├── LogCriteria.java
│ │ │ ├── LogEntry.java
│ │ │ └── MemoryAppender.java
│ │ │ └── mime
│ │ │ ├── MimeType.java
│ │ │ └── MimeTypeUtil.java
│ └── resources
│ │ ├── META-INF
│ │ └── persistence.xml
│ │ ├── adblock
│ │ ├── js
│ │ │ ├── ElemHide.jsm
│ │ │ ├── FilterClasses.jsm
│ │ │ ├── FilterListener.jsm
│ │ │ ├── FilterNotifier.jsm
│ │ │ ├── FilterStorage.jsm
│ │ │ ├── Matcher.jsm
│ │ │ ├── SubscriptionClasses.jsm
│ │ │ ├── Synchronizer.jsm
│ │ │ ├── XMLHttpRequest.jsm
│ │ │ ├── basedomain.js
│ │ │ ├── publicSuffixList.js
│ │ │ ├── punycode.js
│ │ │ └── start.js
│ │ └── subscriptions.xml
│ │ ├── db
│ │ └── update
│ │ │ ├── dbupdate-000-0.sql
│ │ │ ├── dbupdate-001-0.sql
│ │ │ ├── dbupdate-002-0.sql
│ │ │ ├── dbupdate-003-0.sql
│ │ │ ├── dbupdate-004-0.sql
│ │ │ ├── dbupdate-005-0.sql
│ │ │ └── dbupdate-006-0.sql
│ │ ├── messages.properties
│ │ └── messages_fr.properties
│ └── test
│ ├── java
│ └── com
│ │ └── sismics
│ │ ├── reader
│ │ ├── BaseTransactionalTest.java
│ │ └── core
│ │ │ └── dao
│ │ │ ├── file
│ │ │ ├── html
│ │ │ │ ├── TestFaviconDownloader.java
│ │ │ │ ├── TestFaviconExtractor.java
│ │ │ │ └── TestRssExtractor.java
│ │ │ ├── json
│ │ │ │ └── TestStarredReader.java
│ │ │ ├── opml
│ │ │ │ └── TestOpmlReader.java
│ │ │ └── rss
│ │ │ │ └── TestRssReader.java
│ │ │ └── jpa
│ │ │ └── TestJpa.java
│ │ └── util
│ │ ├── TestAdblockUtil.java
│ │ ├── TestArticleSanitizer.java
│ │ ├── TestCertUtil.java
│ │ ├── TestDateUtil.java
│ │ ├── TestNetworkUtil.java
│ │ ├── TestResourceUtil.java
│ │ ├── TestTextSanitizer.java
│ │ └── TestUrlUtil.java
│ └── resources
│ ├── config.properties
│ ├── feed
│ ├── feed_atom_akewea.xml
│ ├── feed_atom_github_user.xml
│ ├── feed_atom_haverbeke.xml
│ ├── feed_atom_makiko.xml
│ ├── feed_atom_marijnhaverbeke.xml
│ ├── feed_atom_ploum.xml
│ ├── feed_atom_whatif.xml
│ ├── feed_atom_whatif2.xml
│ ├── feed_atom_xkcd.xml
│ ├── feed_error_lemessager.html
│ ├── feed_error_toomanyfatalerror.html
│ ├── feed_rdf_autostrip.xml
│ ├── feed_rdf_lxer.xml
│ ├── feed_rdf_meisalam.xml
│ ├── feed_rdf_oatmeal.xml
│ ├── feed_rss2_apod.xml
│ ├── feed_rss2_bysme.xml
│ ├── feed_rss2_cultiz.xml
│ ├── feed_rss2_developerworks.xml
│ ├── feed_rss2_developpez.xml
│ ├── feed_rss2_dilbert.xml
│ ├── feed_rss2_distractionware.xml
│ ├── feed_rss2_distractionware2.xml
│ ├── feed_rss2_esa.xml
│ ├── feed_rss2_fubiz.xml
│ ├── feed_rss2_gizmodo.gzip
│ ├── feed_rss2_ibox.xml
│ ├── feed_rss2_korben.xml
│ ├── feed_rss2_lemessager.xml
│ ├── feed_rss2_maliki.xml
│ ├── feed_rss2_nasa.xml
│ ├── feed_rss2_nova.xml
│ ├── feed_rss2_ploum.xml
│ ├── feed_rss2_rottentomatoes.xml
│ ├── feed_rss2_slackware.xml
│ ├── feed_rss2_slashdot.xml
│ ├── feed_rss2_space.xml
│ ├── feed_rss2_spacedaily.xml
│ └── feed_rss2_xkcd.xml
│ ├── google_takeout
│ └── starred.json
│ ├── hibernate.properties
│ ├── log4j.properties
│ ├── lucene
│ ├── korben_data.xml
│ └── techcrunch_data.xml
│ ├── opml
│ ├── greader_subscriptions.xml
│ ├── liferea_subscriptions.xml
│ └── ttrss_subscriptions.xml
│ └── page
│ ├── korben.html
│ ├── makiko-f.blogspot.fr.html
│ ├── ploum.html
│ ├── space.html
│ └── xkcd.html
├── reader-distribution-debian
├── pom.xml
└── src
│ └── main
│ ├── deb
│ └── control
│ │ ├── conffiles
│ │ ├── control
│ │ ├── postinst
│ │ ├── postrm
│ │ ├── preinst
│ │ └── prerm
│ └── package
│ ├── etc
│ ├── default
│ │ └── reader
│ └── init.d
│ │ └── reader
│ └── usr
│ └── share
│ └── doc
│ └── reader
│ ├── README
│ └── copyright
├── reader-distribution-docker
├── Dockerfile
└── docker-compose.yml
├── reader-distribution-mac
├── pom.xml
└── src
│ └── main
│ └── osxappbundle
│ ├── JavaApplicationStub
│ └── reader-512.icns
├── reader-distribution-redhat
├── pom.xml
└── src
│ └── main
│ ├── package
│ └── etc
│ │ ├── init.d
│ │ └── reader
│ │ └── sysconfig
│ │ └── reader
│ └── rpm
│ └── script
│ ├── postinstall
│ ├── preinstall
│ └── preremove
├── reader-distribution-standalone
├── pom.xml
└── src
│ └── main
│ ├── assembly
│ ├── dist.xml
│ ├── reader.bat
│ └── reader.sh
│ └── java
│ └── com
│ └── sismics
│ └── reader
│ └── Standalone.java
├── reader-distribution-windows
├── pom.xml
└── src
│ └── main
│ ├── launch4j
│ ├── LICENSE.txt
│ ├── reader-16.ico
│ ├── reader-agent-elevated.manifest
│ ├── reader-agent-elevated.xml
│ ├── reader-agent.properties
│ └── reader-agent.xml
│ └── nsis
│ ├── jre-7u21-windows-i586.exe
│ └── reader.nsi
├── reader-web-common
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── com
│ │ └── sismics
│ │ ├── rest
│ │ ├── exception
│ │ │ ├── ClientException.java
│ │ │ ├── ForbiddenClientException.java
│ │ │ └── ServerException.java
│ │ ├── resource
│ │ │ └── GenericExceptionMapper.java
│ │ └── util
│ │ │ ├── JsonUtil.java
│ │ │ └── ValidationUtil.java
│ │ ├── security
│ │ ├── AnonymousPrincipal.java
│ │ ├── IPrincipal.java
│ │ └── UserPrincipal.java
│ │ └── util
│ │ └── filter
│ │ ├── HeaderBasedSecurityFilter.java
│ │ ├── RequestContextFilter.java
│ │ ├── SecurityFilter.java
│ │ └── TokenBasedSecurityFilter.java
│ └── test
│ └── java
│ └── com
│ └── sismics
│ └── reader
│ └── rest
│ ├── BaseJerseyTest.java
│ ├── descriptor
│ └── JerseyTestWebAppDescriptorFactory.java
│ ├── filter
│ └── CookieAuthenticationFilter.java
│ └── util
│ └── TestValidationUtil.java
├── reader-web
├── pom.xml
└── src
│ ├── dev
│ ├── main
│ │ └── webapp
│ │ │ └── web-override.xml
│ └── resources
│ │ ├── hibernate.properties
│ │ └── log4j.properties
│ ├── hosted
│ └── resources
│ │ ├── hibernate.properties
│ │ └── log4j.properties
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── sismics
│ │ │ └── reader
│ │ │ └── rest
│ │ │ ├── assembler
│ │ │ └── ArticleAssembler.java
│ │ │ ├── constant
│ │ │ └── BaseFunction.java
│ │ │ ├── dao
│ │ │ └── ThemeDao.java
│ │ │ ├── resource
│ │ │ ├── AllResource.java
│ │ │ ├── AppResource.java
│ │ │ ├── ArticleResource.java
│ │ │ ├── BaseResource.java
│ │ │ ├── CategoryResource.java
│ │ │ ├── JobResource.java
│ │ │ ├── LocaleResource.java
│ │ │ ├── SearchResource.java
│ │ │ ├── StarredResource.java
│ │ │ ├── SubscriptionResource.java
│ │ │ ├── TextPlainMessageBodyWriter.java
│ │ │ ├── ThemeResource.java
│ │ │ └── UserResource.java
│ │ │ └── util
│ │ │ └── ValidationUtil.java
│ ├── resources
│ │ ├── config.properties
│ │ └── image
│ │ │ └── subscription.png
│ └── webapp
│ │ ├── .gitignore
│ │ ├── Gruntfile.js
│ │ ├── WEB-INF
│ │ └── web.xml
│ │ ├── package.json
│ │ └── src
│ │ ├── favicon.png
│ │ ├── images
│ │ ├── ajax-loader.gif
│ │ ├── category.png
│ │ ├── category_add.png
│ │ ├── edit.png
│ │ ├── error.png
│ │ ├── external.png
│ │ ├── full.png
│ │ ├── jqueryui
│ │ │ ├── animated-overlay.gif
│ │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png
│ │ │ ├── ui-bg_flat_75_ffffff_40x100.png
│ │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png
│ │ │ ├── ui-bg_glass_65_ffffff_1x400.png
│ │ │ ├── ui-bg_glass_75_dadada_1x400.png
│ │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png
│ │ │ ├── ui-bg_glass_95_fef1ec_1x400.png
│ │ │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png
│ │ │ ├── ui-icons_222222_256x240.png
│ │ │ ├── ui-icons_2e83ff_256x240.png
│ │ │ ├── ui-icons_454545_256x240.png
│ │ │ ├── ui-icons_888888_256x240.png
│ │ │ └── ui-icons_cd0a0a_256x240.png
│ │ ├── list.png
│ │ ├── loader.gif
│ │ ├── mime
│ │ │ ├── application.png
│ │ │ ├── audio.png
│ │ │ ├── font.png
│ │ │ ├── image.png
│ │ │ ├── package.png
│ │ │ ├── text.png
│ │ │ └── video.png
│ │ ├── narrow.png
│ │ ├── nostar.png
│ │ ├── notice.png
│ │ ├── read.png
│ │ ├── refresh.png
│ │ ├── rss_icon.png
│ │ ├── rssman.png
│ │ ├── search.png
│ │ ├── settings.png
│ │ ├── share
│ │ │ ├── email.png
│ │ │ ├── facebook.png
│ │ │ ├── googleplus.png
│ │ │ └── twitter.png
│ │ ├── star.png
│ │ ├── subscription.png
│ │ ├── success.png
│ │ ├── tree_minus.gif
│ │ ├── tree_plus.gif
│ │ ├── unread.png
│ │ ├── warning.png
│ │ └── wide.png
│ │ ├── index.html
│ │ ├── javascripts
│ │ ├── jquery.cookie.js
│ │ ├── jquery.history.js
│ │ ├── jquery.i18next.js
│ │ ├── jquery.js
│ │ ├── jquery.json.js
│ │ ├── jquery.less.js
│ │ ├── jquery.moment.js
│ │ ├── jquery.numeral.js
│ │ ├── jquery.qtip.js
│ │ ├── jquery.throttle.js
│ │ ├── jquery.toastmessage.js
│ │ ├── jquery.ui.js
│ │ ├── jquery.validate.js
│ │ ├── jquery.visible.js
│ │ ├── r.about.js
│ │ ├── r.article.js
│ │ ├── r.category.js
│ │ ├── r.feed.js
│ │ ├── r.main.js
│ │ ├── r.search.js
│ │ ├── r.settings.js
│ │ ├── r.shortcuts.js
│ │ ├── r.subscription.js
│ │ ├── r.theme.js
│ │ ├── r.user.js
│ │ ├── r.util.js
│ │ └── r.wizard.js
│ │ ├── locales
│ │ ├── messages.da.js
│ │ ├── messages.de.js
│ │ ├── messages.en.js
│ │ ├── messages.fr.js
│ │ ├── messages.it.js
│ │ ├── messages.ja.js
│ │ ├── messages.ko.js
│ │ ├── messages.zh-CN.js
│ │ ├── messages.zh-HK.js
│ │ ├── messages.zh-TW.js
│ │ └── messages.zh.js
│ │ └── stylesheets
│ │ ├── _desktop.less
│ │ ├── _general.less
│ │ ├── _jquery.toastmessage.less
│ │ ├── _mixins.less
│ │ ├── _smartphone-small.less
│ │ ├── _smartphone.less
│ │ ├── jquery.qtip.css
│ │ ├── jquery.ui.css
│ │ ├── loader.css
│ │ ├── main.less
│ │ └── theme
│ │ ├── dark.less
│ │ ├── default.less
│ │ └── highcontrast.less
│ ├── prod
│ └── resources
│ │ └── log4j.properties
│ └── test
│ ├── java
│ └── com
│ │ └── sismics
│ │ └── reader
│ │ └── rest
│ │ ├── TestAllResource.java
│ │ ├── TestAppResource.java
│ │ ├── TestCategoryResource.java
│ │ ├── TestJobResource.java
│ │ ├── TestLocaleResource.java
│ │ ├── TestSearchResource.java
│ │ ├── TestSecurity.java
│ │ ├── TestStarredResource.java
│ │ ├── TestSubscriptionResource.java
│ │ ├── TestThemeResource.java
│ │ └── TestUserResource.java
│ └── resources
│ ├── hibernate.properties
│ ├── http
│ └── feeds
│ │ ├── androiddev.xml
│ │ ├── bigpicture.xml
│ │ ├── deleted
│ │ ├── deleted0.xml
│ │ ├── deleted1.xml
│ │ └── deleted2.xml
│ │ ├── explosm.xml
│ │ ├── future_date.xml
│ │ ├── issue_119.xml
│ │ ├── korben.xml
│ │ ├── korben2.xml
│ │ ├── qc.xml
│ │ ├── saturdaymorning.xml
│ │ ├── scientopia.xml
│ │ ├── slashdot.xml
│ │ └── xkcd.xml
│ ├── import
│ ├── greader_subscriptions.xml
│ ├── issue_110@gmail.com-takeout.zip
│ └── test@gmail.com-takeout.zip
│ ├── log4j.properties
│ └── stylesheets
│ └── theme
│ ├── default.less
│ └── highcontrast.less
├── reader.xml
└── rssman.ai
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set default behaviour, in case users don't have core.autocrlf set.
2 | * text=auto
3 |
4 | # Explicitly declare text files we want to always be normalized and converted
5 | # to native line endings on checkout.
6 | *.c text
7 | *.h text
8 |
9 | # Declare files that will always have CRLF line endings on checkout.
10 | *.sln text eol=crlf
11 |
12 | # Denote all files that are truly binary and should not be modified.
13 | *.png binary
14 | *.jpg binary
15 |
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /*/.classpath
2 | /*/.project
3 | /*/.settings
4 | /*/bin
5 | /*/gen
6 | /*/target
7 | *.iml
8 | .idea/
9 | /reader-web/src/main/webapp/sismicsreader
10 | /reader-web/src/main/webapp/node
11 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | dist: trusty
2 | language: java
3 | services:
4 | - docker
5 | script:
6 | - if [ "$TRAVIS_BRANCH" == "release" ]; then
7 | mvn -B -Pprod,hosted -DskipTests clean install -pl reader-web,reader-core,reader-web-common;
8 | elif [ "$TRAVIS_BRANCH" == "demo" ]; then
9 | mvn -B -Pprod,demo -DskipTests clean install -pl reader-web,reader-core,reader-web-common;
10 | else
11 | mvn -B test;
12 | fi
13 | after_success:
14 | - if [ "$TRAVIS_BRANCH" == "release" ]; then
15 | docker build -f reader-distribution-docker/Dockerfile -t sismics/reader:latest .;
16 | docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD";
17 | docker push sismics/reader:latest;
18 | elif [ "$TRAVIS_BRANCH" == "demo" ]; then
19 | docker build -f reader-distribution-docker/Dockerfile -t sismics/reader:demo-latest .;
20 | docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD";
21 | docker push sismics/reader:demo-latest;
22 | fi
23 |
--------------------------------------------------------------------------------
/reader-agent/src/main/java/com/sismics/reader/agent/deployer/DeploymentStatusListener.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.agent.deployer;
2 |
3 | /**
4 | * Callback interface implemented by classes that wants to be notified when the state
5 | * of the server deployment changes.
6 | *
7 | * @author jtremeaux
8 | */
9 | public interface DeploymentStatusListener {
10 |
11 | /**
12 | * Method invoked when information about the server deployment is available
13 | *
14 | * @param deploymentStatus Deployment status
15 | */
16 | void notifyDeploymentStatus(DeploymentStatus deploymentStatus);
17 | }
18 |
--------------------------------------------------------------------------------
/reader-agent/src/main/java/com/sismics/util/MessageUtil.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util;
2 |
3 | import java.text.MessageFormat;
4 | import java.util.Locale;
5 | import java.util.MissingResourceException;
6 | import java.util.ResourceBundle;
7 |
8 | /**
9 | * Message utilities.
10 | *
11 | * @author jtremeaux
12 | */
13 | public class MessageUtil {
14 | private static final Locale locale = Locale.getDefault();
15 |
16 | /**
17 | * Returns a message formated in the specified locale.
18 | * Returns **key** if no message is set for this key.
19 | *
20 | * @param key Message key
21 | * @param args Arguments of the message
22 | * @return Formated message
23 | */
24 | public static String getMessage(String key, Object... args) {
25 | ResourceBundle resources = ResourceBundle.getBundle("messages", locale);
26 | String message = null;
27 | try {
28 | message = resources.getString(key);
29 | } catch (MissingResourceException e) {
30 | message = "**" + key + "**";
31 | }
32 | return MessageFormat.format(message, args);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/reader-agent/src/main/resources/images/reader-started-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-agent/src/main/resources/images/reader-started-16.png
--------------------------------------------------------------------------------
/reader-agent/src/main/resources/images/reader-stopped-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-agent/src/main/resources/images/reader-stopped-16.png
--------------------------------------------------------------------------------
/reader-agent/src/main/resources/messages_fr.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-agent/src/main/resources/messages_fr.properties
--------------------------------------------------------------------------------
/reader-android/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea
4 | build
5 | *.iml
--------------------------------------------------------------------------------
/reader-android/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/reader-android/app/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | jcenter()
4 | google()
5 | }
6 | dependencies {
7 | classpath 'com.android.tools.build:gradle:3.3.0'
8 | }
9 | }
10 |
11 | apply plugin: 'com.android.application'
12 |
13 | repositories {
14 | mavenCentral()
15 | google()
16 | flatDir { dirs 'libs' }
17 | }
18 |
19 | android {
20 | compileSdkVersion 28
21 | useLibrary 'org.apache.http.legacy'
22 |
23 | defaultConfig {
24 | minSdkVersion 14
25 | targetSdkVersion 28
26 | versionCode 12
27 | versionName "1.6.0"
28 | }
29 |
30 | signingConfigs {
31 | release {
32 | storeFile file(String.valueOf(System.getenv("READER_STORE_PATH")))
33 | storePassword String.valueOf(System.getenv("READER_STORE_PASS"))
34 | keyAlias String.valueOf(System.getenv("READER_STORE_ALIAS"))
35 | keyPassword String.valueOf(System.getenv("READER_STORE_KEYPASS"))
36 | }
37 | }
38 |
39 | buildTypes {
40 | release {
41 | signingConfig signingConfigs.release
42 | }
43 | }
44 | }
45 |
46 | dependencies {
47 | implementation fileTree(dir: 'libs', include: '*.jar')
48 | implementation 'com.android.support:support-v4:28.0.0'
49 | implementation 'com.android.support:appcompat-v7:28.0.0'
50 | implementation 'com.mobeta.android.dslv:drag-sort-listview:0.6.1-SNAPSHOT-AAR@aar'
51 | implementation 'com.loopj.android:android-async-http:1.4.4'
52 | }
--------------------------------------------------------------------------------
/reader-android/app/libs/android-query.0.26.7.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/libs/android-query.0.26.7.jar
--------------------------------------------------------------------------------
/reader-android/app/libs/drag-sort-listview-0.6.1-SNAPSHOT-AAR.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/libs/drag-sort-listview-0.6.1-SNAPSHOT-AAR.aar
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/android/util/DialogUtil.java:
--------------------------------------------------------------------------------
1 | package com.sismics.android.util;
2 |
3 | import android.app.Activity;
4 | import android.app.AlertDialog;
5 | import android.content.DialogInterface;
6 |
7 | import com.sismics.reader.R;
8 |
9 | /**
10 | * Utility class for dialogs.
11 | *
12 | * @author bgamard
13 | */
14 | public class DialogUtil {
15 |
16 | /**
17 | * Create a dialog with an OK button.
18 | *
19 | * @param activity Context activity
20 | * @param title Dialog title
21 | * @param message Dialog message
22 | */
23 | public static void showOkDialog(Activity activity, int title, int message) {
24 | if (activity == null || activity.isFinishing()) {
25 | return;
26 | }
27 |
28 | AlertDialog.Builder builder = new AlertDialog.Builder(activity);
29 |
30 | builder.setTitle(title)
31 | .setMessage(message)
32 | .setCancelable(true)
33 | .setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() {
34 | @Override
35 | public void onClick(DialogInterface dialog, int id) {
36 | dialog.dismiss();
37 | }
38 | }).create().show();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader;
2 |
3 | import android.app.Application;
4 |
5 | import com.androidquery.callback.BitmapAjaxCallback;
6 | import com.sismics.reader.model.application.ApplicationContext;
7 | import com.sismics.reader.util.PreferenceUtil;
8 |
9 | import org.json.JSONObject;
10 |
11 | /**
12 | * Main application.
13 | *
14 | * @author bgamard
15 | */
16 | public class MainApplication extends Application {
17 | @Override
18 | public void onCreate() {
19 | // Fetching /user/info from cache
20 | JSONObject json = PreferenceUtil.getCachedJson(getApplicationContext(), PreferenceUtil.PREF_CACHED_USER_INFO_JSON);
21 | ApplicationContext.getInstance().setUserInfo(getApplicationContext(), json);
22 |
23 | // TODO Changing the category of a subscription
24 | // TODO Renaming subscriptions
25 | // TODO Deleting subscriptions
26 | // TODO Admin interface if the user is admin
27 |
28 | // TODO Articles drawer: select article on opening
29 |
30 | super.onCreate();
31 | }
32 |
33 | @Override
34 | public void onLowMemory() {
35 | super.onLowMemory();
36 | BitmapAjaxCallback.clearCache();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/activity/LicenseActivity.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.text.Html;
6 | import android.text.method.LinkMovementMethod;
7 | import android.view.MenuItem;
8 |
9 | import com.androidquery.AQuery;
10 | import com.sismics.reader.R;
11 |
12 | /**
13 | * Open source licenses activity.
14 | *
15 | * @author bgamard
16 | */
17 | public class LicenseActivity extends AppCompatActivity {
18 |
19 | /**
20 | * AQuery.
21 | */
22 | final AQuery aq = new AQuery(this);
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 |
28 | setContentView(R.layout.license_activity);
29 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
30 | getSupportActionBar().setHomeButtonEnabled(true);
31 |
32 | aq.id(R.id.txtLicenses)
33 | .text(Html.fromHtml(getString(R.string.licenses_content)))
34 | .getTextView()
35 | .setMovementMethod(LinkMovementMethod.getInstance());
36 | }
37 |
38 | @Override
39 | public boolean onOptionsItemSelected(MenuItem item) {
40 | switch (item.getItemId()) {
41 | case android.R.id.home:
42 | finish();
43 | return true;
44 | }
45 |
46 | return super.onOptionsItemSelected(item);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/activity/SettingsActivity.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.view.MenuItem;
6 |
7 | import com.sismics.reader.fragment.SettingsFragment;
8 |
9 | /**
10 | * Settings activity.
11 | *
12 | * @author bgamard.
13 | */
14 | public class SettingsActivity extends AppCompatActivity {
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 |
20 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
21 | getSupportActionBar().setHomeButtonEnabled(true);
22 |
23 | // Display the fragment as the main content.
24 | getFragmentManager().beginTransaction()
25 | .replace(android.R.id.content, new SettingsFragment())
26 | .commit();
27 | }
28 |
29 | @Override
30 | public boolean onOptionsItemSelected(MenuItem item) {
31 | switch (item.getItemId()) {
32 | case android.R.id.home:
33 | finish();
34 | return true;
35 | }
36 |
37 | return super.onOptionsItemSelected(item);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/constant/Constants.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.constant;
2 |
3 |
4 | /**
5 | * Application constants.
6 | *
7 | * @author bgamard
8 | */
9 | public class Constants {
10 | /**
11 | * Request code from articles list.
12 | */
13 | public static final int REQUEST_CODE_ARTICLES = 1;
14 |
15 | /**
16 | * Request code for managing activities.
17 | */
18 | public static final int REQUEST_CODE_MANAGE_CATEGORIES = 2;
19 | }
20 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/fragment/ArticlesDefaultFragment.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.fragment;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import com.androidquery.AQuery;
9 | import com.sismics.reader.R;
10 |
11 | /**
12 | * Articles default fragment.
13 | *
14 | * @author bgamard
15 | */
16 | public class ArticlesDefaultFragment extends NavigationFragment {
17 |
18 | /**
19 | * AQuery.
20 | */
21 | private AQuery aq;
22 |
23 | @Override
24 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
25 | View view = inflater.inflate(R.layout.articles_fragment, container, false);
26 | aq = new AQuery(view);
27 | aq.id(R.id.articleList).getListView().setEmptyView(aq.id(R.id.progressBar).getView());
28 | aq.id(R.id.loadingText).text(R.string.loading_subscriptions);
29 |
30 | return view;
31 | }
32 |
33 | /**
34 | * Listen to subscription loading error.
35 | */
36 | public void onSubscriptionError() {
37 | aq.id(R.id.emptyList).text(R.string.error_loading_subscriptions)
38 | .getTextView()
39 | .setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, R.drawable.character_sad);
40 | aq.id(R.id.articleList).getListView().setEmptyView(aq.id(R.id.emptyList).getView());
41 | aq.id(R.id.progressBar).gone();
42 | }
43 | }
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/fragment/NavigationFragment.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.fragment;
2 |
3 | import android.support.v4.app.Fragment;
4 |
5 |
6 | /**
7 | * Base navigation fragment.
8 | *
9 | * @author bgamard
10 | */
11 | public class NavigationFragment extends Fragment {
12 | }
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/listener/ArticlesHelperListener.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.listener;
2 |
3 | /**
4 | * Listener on articles loading.
5 |
6 | * @author bgamard
7 | */
8 | public interface ArticlesHelperListener {
9 |
10 | /**
11 | * Start loading articles.
12 | */
13 | public void onStart();
14 |
15 | /**
16 | * Articles successfully loaded.
17 | */
18 | public void onSuccess();
19 |
20 | /**
21 | * Error occurred while loading the articles.
22 | */
23 | public void onError();
24 |
25 | /**
26 | * End loading new articles.
27 | */
28 | public void onEnd();
29 | }
30 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/listener/CallbackListener.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.listener;
2 |
3 | /**
4 | * Simple listener.
5 | *
6 | * @author bgamard
7 | */
8 | public interface CallbackListener {
9 | public void onComplete();
10 | }
11 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/provider/RecentSuggestionsProvider.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.provider;
2 |
3 | import android.content.SearchRecentSuggestionsProvider;
4 |
5 | /**
6 | * Search recent suggestions provider.
7 | *
8 | * @author bgamard.
9 | */
10 | public class RecentSuggestionsProvider extends SearchRecentSuggestionsProvider {
11 | public final static String AUTHORITY = "com.sismics.reader.provider.RecentSuggestionsProvider";
12 | public final static int MODE = DATABASE_MODE_QUERIES;
13 |
14 | public RecentSuggestionsProvider() {
15 | setupSuggestions(AUTHORITY, MODE);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/ui/adapter/ArticlesPagerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.ui.adapter;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.support.v4.app.FragmentManager;
5 | import android.support.v4.app.FragmentStatePagerAdapter;
6 |
7 | import com.sismics.reader.fragment.ArticleFragment;
8 |
9 | import org.json.JSONObject;
10 |
11 | import java.util.List;
12 |
13 |
14 | /**
15 | * Adapter for articles ViewPager.
16 | *
17 | * @author bgamard
18 | */
19 | public class ArticlesPagerAdapter extends FragmentStatePagerAdapter {
20 | /**
21 | * Constructor.
22 | * @param fm FragmentManager
23 | */
24 | public ArticlesPagerAdapter(FragmentManager fm) {
25 | super(fm);
26 | }
27 |
28 | @Override
29 | public Fragment getItem(int position) {
30 | JSONObject article = SharedArticlesAdapterHelper.getInstance().getArticleItems().get(position);
31 | return ArticleFragment.newInstance(article);
32 | }
33 |
34 | @Override
35 | public int getCount() {
36 | return SharedArticlesAdapterHelper.getInstance().getArticleItems().size();
37 | }
38 |
39 | @Override
40 | public int getItemPosition(Object object) {
41 | return POSITION_UNCHANGED;
42 | // Do not return POSITION_NONE all the time or the whole fragment will be invalidated
43 | // return POSITION_NONE;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/ui/form/Validable.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.ui.form;
2 |
3 | import android.view.View;
4 |
5 | public class Validable {
6 |
7 | private View view;
8 |
9 | private boolean isValidated = false;
10 |
11 | /**
12 | * Getter of view.
13 | * @return view
14 | */
15 | public View getView() {
16 | return view;
17 | }
18 |
19 | /**
20 | * Setter of view.
21 | * @param view view
22 | */
23 | public void setView(View view) {
24 | this.view = view;
25 | }
26 |
27 | /**
28 | * Getter of isValidated.
29 | * @return isValidated
30 | */
31 | public boolean isValidated() {
32 | return isValidated;
33 | }
34 |
35 | /**
36 | * Setter of isValidated.
37 | * @param isValidated isValidated
38 | */
39 | public void setValidated(boolean isValidated) {
40 | this.isValidated = isValidated;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/ui/form/validator/Alphanumeric.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.ui.form.validator;
2 |
3 | import java.util.regex.Pattern;
4 |
5 | import android.content.Context;
6 |
7 | import com.sismics.reader.R;
8 |
9 | /**
10 | * Alphanumeric validator.
11 | *
12 | * @author bgamard
13 | */
14 | public class Alphanumeric implements ValidatorType {
15 |
16 | private static Pattern ALPHANUMERIC_PATTERN = Pattern.compile("[a-zA-Z0-9_]+");
17 |
18 | @Override
19 | public boolean validate(String text) {
20 | return ALPHANUMERIC_PATTERN.matcher(text).matches();
21 | }
22 |
23 | @Override
24 | public String getErrorMessage(Context context) {
25 | return context.getString(R.string.validate_error_alphanumeric);
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/ui/form/validator/Email.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.ui.form.validator;
2 |
3 | import java.util.regex.Pattern;
4 |
5 | import android.content.Context;
6 |
7 | import com.sismics.reader.R;
8 |
9 | /**
10 | * Email validator.
11 | *
12 | * @author bgamard
13 | */
14 | public class Email implements ValidatorType {
15 |
16 | /**
17 | * Pattern de validation.
18 | */
19 | private static Pattern EMAIL_PATTERN = Pattern.compile(".+@.+\\..+");
20 |
21 | @Override
22 | public boolean validate(String text) {
23 | return EMAIL_PATTERN.matcher(text).matches();
24 | }
25 |
26 | @Override
27 | public String getErrorMessage(Context context) {
28 | return context.getResources().getString(R.string.validate_error_email);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/ui/form/validator/Length.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.ui.form.validator;
2 |
3 | import android.content.Context;
4 |
5 | import com.sismics.reader.R;
6 |
7 | /**
8 | * Text length validator.
9 | *
10 | * @author bgamard
11 | */
12 | public class Length implements ValidatorType {
13 |
14 | /**
15 | * Minimum length.
16 | */
17 | private int minLength = 0;
18 |
19 | /**
20 | * Maximum length.
21 | */
22 | private int maxLength = 0;
23 |
24 | /**
25 | * True if the last validation error was about a string too short.
26 | */
27 | private boolean tooShort;
28 |
29 | /**
30 | * Constructor.
31 | * @param minLength
32 | * @param maxLength
33 | */
34 | public Length(int minLength, int maxLength) {
35 | this.minLength = minLength;
36 | this.maxLength = maxLength;
37 | }
38 |
39 | @Override
40 | public boolean validate(String text) {
41 | tooShort = text.trim().length() < minLength;
42 | return text.trim().length() >= minLength && text.trim().length() <= maxLength;
43 | }
44 |
45 | @Override
46 | public String getErrorMessage(Context context) {
47 | if (tooShort) {
48 | return context.getResources().getString(R.string.validate_error_length_min, minLength);
49 | }
50 | return context.getResources().getString(R.string.validate_error_length_max, maxLength);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/ui/form/validator/Required.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.ui.form.validator;
2 |
3 | import android.content.Context;
4 |
5 | import com.sismics.reader.R;
6 |
7 | /**
8 | * Text presence validator.
9 | *
10 | * @author bgamard
11 | */
12 | public class Required implements ValidatorType {
13 |
14 | @Override
15 | public boolean validate(String text) {
16 | return text.trim().length() != 0;
17 | }
18 |
19 | @Override
20 | public String getErrorMessage(Context context) {
21 | return context.getString(R.string.validate_error_required);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/ui/form/validator/ValidatorType.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.ui.form.validator;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * Interface for validation types.
7 | *
8 | * @author bgamard
9 | */
10 | public interface ValidatorType {
11 |
12 | /**
13 | * Returns true if the validator is validated.
14 | * @param text
15 | * @return
16 | */
17 | public boolean validate(String text);
18 |
19 | /**
20 | * Returns an error message.
21 | * @param context
22 | * @return
23 | */
24 | public String getErrorMessage(Context context);
25 | }
26 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/ui/widget/ArticlesSwipeRefreshLayout.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.ui.widget;
2 |
3 | import android.content.Context;
4 | import android.support.v4.widget.SwipeRefreshLayout;
5 | import android.util.AttributeSet;
6 | import android.widget.ListView;
7 |
8 | import com.sismics.reader.R;
9 |
10 | /**
11 | * Subclassing of SwipeRefreshLayout to handle our custom case.
12 | *
13 | * @author bgamard.
14 | */
15 | public class ArticlesSwipeRefreshLayout extends SwipeRefreshLayout {
16 | public ArticlesSwipeRefreshLayout(Context context) {
17 | super(context);
18 | }
19 |
20 | public ArticlesSwipeRefreshLayout(Context context, AttributeSet attrs) {
21 | super(context, attrs);
22 | }
23 |
24 | @Override
25 | public boolean canChildScrollUp() {
26 | ListView listView = (ListView) findViewById(R.id.articleList);
27 | return listView != null && listView.getChildCount() > 0
28 | && (listView.getFirstVisiblePosition() > 0 || listView.getChildAt(0)
29 | .getTop() < listView.getPaddingTop());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/java/com/sismics/reader/util/ApplicationUtil.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.util;
2 |
3 | import android.content.Context;
4 | import android.content.pm.PackageInfo;
5 | import android.content.pm.PackageManager.NameNotFoundException;
6 |
7 | /**
8 | * Utility class on general application data.
9 | *
10 | * @author bgamard
11 | */
12 | public class ApplicationUtil {
13 |
14 | /**
15 | * Returns version name.
16 | *
17 | * @param context
18 | * @return Nom de la version
19 | */
20 | public static String getVersionName(Context context) {
21 | try {
22 | PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
23 | return packageInfo.versionName;
24 | } catch (NameNotFoundException e) {
25 | return "";
26 | }
27 | }
28 |
29 | /**
30 | * Returns version number.
31 | *
32 | * @param context
33 | * @return Numéro de version
34 | */
35 | public static int getVersionCode(Context context) {
36 | try {
37 | PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
38 | return packageInfo.versionCode;
39 | } catch (NameNotFoundException e) {
40 | return 0;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/anim/rssman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
13 |
14 |
21 |
22 |
29 |
30 |
37 |
38 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/character.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/character.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/character_happy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/character_happy.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/character_sad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/character_sad.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_about.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_accept.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_accept.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_collection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_collection.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_collection_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_collection_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_collection_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_collection_new.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_important.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_important.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_important_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_important_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_new_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_new_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_not_important.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_not_important.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_not_important_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_not_important_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_read.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_read.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_read_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_read_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_settings.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_share_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_share_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_sort_by_size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_sort_by_size.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_unread.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_unread.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_action_unread_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_action_unread_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_drag.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_drag.9.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_menu_moreoverflow_card_inverse_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_menu_moreoverflow_card_inverse_normal.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/ic_menu_moreoverflow_card_inverse_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/ic_menu_moreoverflow_card_inverse_pressed.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/list_activated_holo.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/list_activated_holo.9.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-hdpi/list_background_holo.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-hdpi/list_background_holo.9.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-sw600dp-hdpi/list_activated_holo.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-sw600dp-hdpi/list_activated_holo.9.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-sw600dp-hdpi/list_background_holo.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-sw600dp-hdpi/list_background_holo.9.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-sw600dp-xhdpi/list_activated_holo.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-sw600dp-xhdpi/list_activated_holo.9.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-sw600dp-xhdpi/list_background_holo.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-sw600dp-xhdpi/list_background_holo.9.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/character.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/character.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/character_happy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/character_happy.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/character_sad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/character_sad.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_about.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_accept.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_accept.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_collection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_collection.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_collection_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_collection_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_collection_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_collection_new.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_important.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_important.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_important_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_important_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_new_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_new_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_not_important.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_not_important.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_not_important_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_not_important_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_read.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_read.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_read_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_read_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_settings.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_share_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_share_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_sort_by_size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_sort_by_size.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_unread.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_unread.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_action_unread_inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_action_unread_inverse.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_drag.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_drag.9.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_menu_moreoverflow_card_inverse_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_menu_moreoverflow_card_inverse_normal.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/ic_menu_moreoverflow_card_inverse_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/ic_menu_moreoverflow_card_inverse_pressed.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/list_activated_holo.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/list_activated_holo.9.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xhdpi/list_background_holo.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xhdpi/list_background_holo.9.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/app/src/main/res/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable/article_title_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable/drawer_list_item_collection.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable/drawer_list_item_important.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable/drawer_list_item_read.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable/drawer_list_item_text_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable/drawer_list_item_unread.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable/list_item_activated_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/drawable/overflow_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/layout/actionbar_indeterminate_progress.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/layout/add_subscription_dialog_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
14 |
15 |
21 |
22 |
27 |
28 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/layout/articles_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
15 |
26 |
27 |
34 |
35 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/layout/drawer_list_item_header.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
21 |
22 |
27 |
28 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/layout/license_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/menu/article_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/menu/categories_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/menu/category_overflow_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/menu/context_articles.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/values-de/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | - Ungelesen
6 | - Alle
7 | - Favoriten
8 |
9 |
10 |
11 | - Klein
12 | - Normal
13 | - Groß
14 |
15 |
16 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/values-w720dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40dp
4 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | - 10
6 | - 15
7 | - 20
8 | - 30
9 |
10 |
11 |
12 | - Unread
13 | - All
14 | - Starred
15 |
16 |
17 |
18 | - 1
19 | - 2
20 | - 3
21 |
22 |
23 |
24 | - Small
25 | - Normal
26 | - Large
27 |
28 |
29 | - 10
30 | - 12
31 | - 14
32 |
33 |
34 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #2ab0e0
4 | #0099cc
5 | #aa66cc
6 | #9933cc
7 | #50ffffff
8 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 8dp
4 | 0dp
5 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
16 |
17 |
21 |
22 |
--------------------------------------------------------------------------------
/reader-android/app/src/main/res/xml/searchable.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/reader-android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
--------------------------------------------------------------------------------
/reader-android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismics/reader/b1c6506462d7980244034ac102ebe1544db9b16e/reader-android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/reader-android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Feb 06 13:36:50 CET 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
7 |
--------------------------------------------------------------------------------
/reader-android/lint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/reader-android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/reader-core/src/dev/resources/db/update/dbupdate-000-2-test.sql:
--------------------------------------------------------------------------------
1 | update T_CONFIG set CFG_VALUE_C = 'RAM' where CFG_ID_C = 'LUCENE_DIRECTORY_STORAGE';
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/constant/ConfigType.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.constant;
2 |
3 | /**
4 | * Configuration parameters.
5 | *
6 | * @author jtremeaux
7 | */
8 | public enum ConfigType {
9 | /**
10 | * Lucene directory storage type.
11 | */
12 | LUCENE_DIRECTORY_STORAGE,
13 | }
14 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/file/html/FeedChooserStrategy.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.file.html;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Strategy used to guess the URL of a RSS / Atom feed when several are present.
7 | *
8 | * @author jtremeaux
9 | */
10 | public class FeedChooserStrategy {
11 |
12 | /**
13 | * Guess the correct feed URL from a set of links.
14 | *
15 | * @param feedList List of links
16 | * @return Feed URL
17 | */
18 | public String guess(List feedList) {
19 | return feedList.get(0);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/file/json/StarredArticleImportedEvent.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.file.json;
2 |
3 | import com.google.common.base.Objects;
4 | import com.sismics.reader.core.model.jpa.Article;
5 | import com.sismics.reader.core.model.jpa.Feed;
6 |
7 | /**
8 | * Event raised on starred articles imported.
9 | *
10 | * @author jtremeaux
11 | */
12 | public class StarredArticleImportedEvent {
13 | private Feed feed;
14 |
15 | private Article article;
16 |
17 | /**
18 | * Getter of feed.
19 | *
20 | * @return feed
21 | */
22 | public Feed getFeed() {
23 | return feed;
24 | }
25 |
26 | /**
27 | * Setter of feed.
28 | *
29 | * @param feed feed
30 | */
31 | public void setFeed(Feed feed) {
32 | this.feed = feed;
33 | }
34 |
35 | /**
36 | * Getter of article.
37 | *
38 | * @return article
39 | */
40 | public Article getArticle() {
41 | return article;
42 | }
43 |
44 | /**
45 | * Setter of article.
46 | *
47 | * @param article article
48 | */
49 | public void setArticle(Article article) {
50 | this.article = article;
51 | }
52 |
53 | @Override
54 | public String toString() {
55 | return Objects.toStringHelper(this)
56 | .add("feed", feed)
57 | .add("article", article)
58 | .toString();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/file/json/StarredArticleImportedListener.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.file.json;
2 |
3 | /**
4 | * Listener for starred item import events.
5 | *
6 | * @author jtremeaux
7 | */
8 | public interface StarredArticleImportedListener {
9 | /**
10 | * Invoked when a new starred item is imported.
11 | *
12 | * @param event Event
13 | */
14 | void onStarredArticleImported(StarredArticleImportedEvent event);
15 | }
16 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/file/rss/AtomArticleCommentUrlGuesserStrategy.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.file.rss;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Guess the article comment URL from a set of links.
7 | *
8 | * @author jtremeaux
9 | */
10 | public class AtomArticleCommentUrlGuesserStrategy {
11 |
12 | /**
13 | * Guess the correct Site URL from a set of links.
14 | *
15 | * @param atomLinkList List of links
16 | * @return Site URL
17 | */
18 | public String guess(List atomLinkList) {
19 | if (atomLinkList == null || atomLinkList.isEmpty()) {
20 | return null;
21 | }
22 |
23 | // 1st try: link with "replies" rel and html content type
24 | for (AtomLink atomLink : atomLinkList) {
25 | if ("replies".equals(atomLink.getRel()) && "text/html".equals(atomLink.getType())) {
26 | return atomLink.getHref();
27 | }
28 | }
29 |
30 | // 2nd try: any link with "replies" rel
31 | for (AtomLink atomLink : atomLinkList) {
32 | if ("replies".equals(atomLink.getRel())) {
33 | return atomLink.getHref();
34 | }
35 | }
36 |
37 | // Default: no comment link present
38 | return null;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/file/rss/AtomArticleUrlGuesserStrategy.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.file.rss;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Guess the article URL from a set of links.
7 | *
8 | * @author jtremeaux
9 | */
10 | public class AtomArticleUrlGuesserStrategy {
11 |
12 | /**
13 | * Guess the correct article URL from a set of links.
14 | *
15 | * @param atomLinkList List of links
16 | * @return Site URL
17 | */
18 | public String guess(List atomLinkList) {
19 | if (atomLinkList == null || atomLinkList.isEmpty()) {
20 | return null;
21 | }
22 |
23 | // 1st try: link from the - element
24 | for (AtomLink atomLink : atomLinkList) {
25 | if (atomLink.getRel() == null && atomLink.getType() == null) {
26 | return atomLink.getHref();
27 | }
28 | }
29 |
30 | // 2nd try: link from the element
31 | for (AtomLink atomLink : atomLinkList) {
32 | if ("alternate".equals(atomLink.getRel()) && "text/html".equals(atomLink.getType())) {
33 | return atomLink.getHref();
34 | }
35 | }
36 |
37 | // Default: return the first link
38 | return atomLinkList.get(0).getHref();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/file/rss/GuidFixer.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.file.rss;
2 |
3 | import org.apache.commons.lang.StringUtils;
4 |
5 | import com.google.common.hash.Hasher;
6 | import com.google.common.hash.Hashing;
7 | import com.sismics.reader.core.model.jpa.Article;
8 |
9 | /**
10 | * Complete the GUID of articles.
11 | *
12 | * @author jtremeaux
13 | */
14 | public class GuidFixer {
15 |
16 | /**
17 | * Complete the GUID of an article.
18 | *
19 | * @param article Article to complete (modified by side effect)
20 | */
21 | public static void fixGuid(Article article) {
22 | if (StringUtils.isBlank(article.getGuid())) {
23 | Hasher hasher = Hashing.sha1().newHasher();
24 | if (StringUtils.isNotBlank(article.getUrl())) {
25 | hasher.putString(article.getUrl());
26 | } else {
27 | if (StringUtils.isNotBlank(article.getTitle())) {
28 | hasher.putString(article.getTitle());
29 | } else if (StringUtils.isNotBlank(article.getDescription())) {
30 | hasher.putString(article.getDescription());
31 | }
32 | }
33 | article.setGuid(hasher.hash().toString());
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/ConfigDao.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa;
2 |
3 | import javax.persistence.EntityManager;
4 | import javax.persistence.NoResultException;
5 |
6 | import com.sismics.reader.core.constant.ConfigType;
7 | import com.sismics.reader.core.model.jpa.Config;
8 | import com.sismics.util.context.ThreadLocalContext;
9 |
10 | /**
11 | * Configuration parameter DAO.
12 | *
13 | * @author jtremeaux
14 | */
15 | public class ConfigDao {
16 | /**
17 | * Gets a configuration parameter by its ID.
18 | *
19 | * @param id Configuration parameter ID
20 | * @return Configuration parameter
21 | */
22 | public Config getById(ConfigType id) {
23 | EntityManager em = ThreadLocalContext.get().getEntityManager();
24 |
25 | // Prevents from getting parameters outside of a transactional context (e.g. jUnit)
26 | if (em == null) {
27 | return null;
28 | }
29 |
30 | try {
31 | return em.find(Config.class, id);
32 | } catch (NoResultException e) {
33 | return null;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/LocaleDao.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa;
2 |
3 | import java.util.List;
4 |
5 | import javax.persistence.EntityManager;
6 | import javax.persistence.NoResultException;
7 | import javax.persistence.Query;
8 |
9 | import com.sismics.reader.core.model.jpa.Locale;
10 | import com.sismics.util.context.ThreadLocalContext;
11 |
12 | /**
13 | * Locale DAO.
14 | *
15 | * @author jtremeaux
16 | */
17 | public class LocaleDao {
18 | /**
19 | * Gets a locale by its ID.
20 | *
21 | * @param id Locale ID
22 | * @return Locale
23 | */
24 | public Locale getById(String id) {
25 | EntityManager em = ThreadLocalContext.get().getEntityManager();
26 | try {
27 | return em.find(Locale.class, id);
28 | } catch (NoResultException e) {
29 | return null;
30 | }
31 | }
32 |
33 | /**
34 | * Returns the list of all locales.
35 | *
36 | * @return List of locales
37 | */
38 | @SuppressWarnings("unchecked")
39 | public List findAll() {
40 | EntityManager em = ThreadLocalContext.get().getEntityManager();
41 | Query q = em.createQuery("select l from Locale l order by l.id");
42 | return q.getResultList();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/RoleBaseFunctionDao.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa;
2 |
3 | import com.google.common.collect.Sets;
4 | import com.sismics.util.context.ThreadLocalContext;
5 |
6 | import javax.persistence.EntityManager;
7 | import javax.persistence.Query;
8 | import java.util.Set;
9 |
10 | /**
11 | * Role base functions DAO.
12 | *
13 | * @author jtremeaux
14 | */
15 | public class RoleBaseFunctionDao {
16 | /**
17 | * Find the set of base functions of a role.
18 | *
19 | * @param roleId Role ID
20 | * @return Set of base functions
21 | */
22 | @SuppressWarnings("unchecked")
23 | public Set findByRoleId(String roleId) {
24 | EntityManager em = ThreadLocalContext.get().getEntityManager();
25 | StringBuilder sb = new StringBuilder("select rbf.RBF_IDBASEFUNCTION_C from T_ROLE_BASE_FUNCTION rbf, T_ROLE r")
26 | .append(" where rbf.RBF_IDROLE_C = :roleId and rbf.RBF_DELETEDATE_D is null")
27 | .append(" and r.ROL_ID_C = rbf.RBF_IDROLE_C and r.ROL_DELETEDATE_D is null");
28 | Query q = em.createNativeQuery(sb.toString())
29 | .setParameter("roleId", roleId);
30 | return Sets.newHashSet(q.getResultList());
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/criteria/FeedCriteria.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa.criteria;
2 |
3 | /**
4 | * Feed criteria.
5 | *
6 | * @author jtremeaux
7 | */
8 | public class FeedCriteria {
9 | /**
10 | * Feed URL.
11 | */
12 | private String feedUrl;
13 |
14 | /**
15 | * Returns only feed having user subscriptions.
16 | */
17 | private boolean withUserSubscription;
18 |
19 | /**
20 | * Getter of feedUrl.
21 | *
22 | * @return feedUrl
23 | */
24 | public String getFeedUrl() {
25 | return feedUrl;
26 | }
27 |
28 | /**
29 | * Setter of feedUrl.
30 | *
31 | * @param feedUrl feedUrl
32 | */
33 | public FeedCriteria setFeedUrl(String feedUrl) {
34 | this.feedUrl = feedUrl;
35 | return this;
36 | }
37 |
38 | /**
39 | * Getter of withUserSubscription.
40 | *
41 | * @return withUserSubscription
42 | */
43 | public boolean isWithUserSubscription() {
44 | return withUserSubscription;
45 | }
46 |
47 | /**
48 | * Setter of withUserSubscription.
49 | *
50 | * @param withUserSubscription withUserSubscription
51 | */
52 | public FeedCriteria setWithUserSubscription(boolean withUserSubscription) {
53 | this.withUserSubscription = withUserSubscription;
54 | return this;
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/criteria/JobCriteria.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa.criteria;
2 |
3 | /**
4 | * Job criteria.
5 | *
6 | * @author jtremeaux
7 | */
8 | public class JobCriteria {
9 | /**
10 | * User ID.
11 | */
12 | private String userId;
13 |
14 | /**
15 | * Getter of userId.
16 | *
17 | * @return userId
18 | */
19 | public String getUserId() {
20 | return userId;
21 | }
22 |
23 | /**
24 | * Setter of userId.
25 | *
26 | * @param userId userId
27 | */
28 | public JobCriteria setUserId(String userId) {
29 | this.userId = userId;
30 | return this;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/criteria/JobEventCriteria.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa.criteria;
2 |
3 | /**
4 | * Job event criteria.
5 | *
6 | * @author jtremeaux
7 | */
8 | public class JobEventCriteria {
9 | /**
10 | * Job ID.
11 | */
12 | private String jobId;
13 |
14 | /**
15 | * Getter of jobId.
16 | *
17 | * @return jobId
18 | */
19 | public String getJobId() {
20 | return jobId;
21 | }
22 |
23 | /**
24 | * Setter of jobId.
25 | *
26 | * @param jobId jobId
27 | */
28 | public JobEventCriteria setJobId(String jobId) {
29 | this.jobId = jobId;
30 | return this;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/criteria/UserCriteria.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa.criteria;
2 |
3 | /**
4 | * User criteria.
5 | *
6 | * @author jtremeaux
7 | */
8 | public class UserCriteria {
9 | }
10 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/dto/FeedDto.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa.dto;
2 |
3 | /**
4 | * Feed DTO.
5 | *
6 | * @author jtremeaux
7 | */
8 | public class FeedDto {
9 | /**
10 | * Feed ID.
11 | */
12 | private String id;
13 |
14 | /**
15 | * Feed RSS URL.
16 | */
17 | private String rssUrl;
18 |
19 | /**
20 | * Getter of id.
21 | *
22 | * @return id
23 | */
24 | public String getId() {
25 | return id;
26 | }
27 |
28 | /**
29 | * Setter of id.
30 | *
31 | * @param id id
32 | */
33 | public void setId(String id) {
34 | this.id = id;
35 | }
36 |
37 | /**
38 | * Getter of rssUrl.
39 | *
40 | * @return rssUrl
41 | */
42 | public String getRssUrl() {
43 | return rssUrl;
44 | }
45 |
46 | /**
47 | * Setter of rssUrl.
48 | *
49 | * @param rssUrl rssUrl
50 | */
51 | public void setRssUrl(String rssUrl) {
52 | this.rssUrl = rssUrl;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/dto/JobEventDto.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa.dto;
2 |
3 | /**
4 | * Job DTO.
5 | *
6 | * @author jtremeaux
7 | */
8 | public class JobEventDto {
9 | /**
10 | * Job ID.
11 | */
12 | private String id;
13 |
14 | /**
15 | * Job event name.
16 | */
17 | private String name;
18 |
19 | /**
20 | * Job event value.
21 | */
22 | private String value;
23 |
24 | /**
25 | * Getter of id.
26 | *
27 | * @return id
28 | */
29 | public String getId() {
30 | return id;
31 | }
32 |
33 | /**
34 | * Setter of id.
35 | *
36 | * @param id id
37 | */
38 | public void setId(String id) {
39 | this.id = id;
40 | }
41 |
42 | /**
43 | * Getter of name.
44 | *
45 | * @return name
46 | */
47 | public String getName() {
48 | return name;
49 | }
50 |
51 | /**
52 | * Setter of name.
53 | *
54 | * @param name name
55 | */
56 | public void setName(String name) {
57 | this.name = name;
58 | }
59 |
60 | /**
61 | * Getter of value.
62 | *
63 | * @return value
64 | */
65 | public String getValue() {
66 | return value;
67 | }
68 |
69 | /**
70 | * Setter of value.
71 | *
72 | * @param value value
73 | */
74 | public void setValue(String value) {
75 | this.value = value;
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/mapper/ArticleMapper.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa.mapper;
2 |
3 | import com.sismics.reader.core.dao.jpa.dto.ArticleDto;
4 | import com.sismics.util.jpa.ResultMapper;
5 |
6 | /**
7 | * @author jtremeaux
8 | */
9 | public class ArticleMapper extends ResultMapper {
10 | @Override
11 | public ArticleDto map(Object[] o) {
12 | int i = 0;
13 | ArticleDto dto = new ArticleDto();
14 | dto.setId(stringValue(o[i++]));
15 | dto.setUrl(stringValue(o[i++]));
16 | dto.setGuid(stringValue(o[i++]));
17 | dto.setTitle(stringValue(o[i++]));
18 | dto.setCreator(stringValue(o[i++]));
19 | dto.setDescription(stringValue(o[i++]));
20 | dto.setCommentUrl(stringValue(o[i++]));
21 | dto.setCommentCount(intValue(o[i++]));
22 | dto.setEnclosureUrl(stringValue(o[i++]));
23 | dto.setEnclosureCount(intValue(o[i++]));
24 | dto.setEnclosureType(stringValue(o[i++]));
25 | dto.setPublicationDate(dateValue(o[i++]));
26 | dto.setCreateDate(dateValue(o[i++]));
27 | dto.setFeedId(stringValue(o[i]));
28 |
29 | return dto;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/mapper/FeedMapper.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa.mapper;
2 |
3 | import com.sismics.reader.core.dao.jpa.dto.FeedDto;
4 | import com.sismics.util.jpa.ResultMapper;
5 |
6 | /**
7 | * @author jtremeaux
8 | */
9 | public class FeedMapper extends ResultMapper {
10 | @Override
11 | public FeedDto map(Object[] o) {
12 | int i = 0;
13 | FeedDto dto = new FeedDto();
14 | dto.setId(stringValue(o[i++]));
15 | dto.setRssUrl(stringValue(o[i]));
16 |
17 | return dto;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/mapper/FeedSubscriptionMapper.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa.mapper;
2 |
3 | import com.sismics.reader.core.dao.jpa.dto.FeedSubscriptionDto;
4 | import com.sismics.util.jpa.ResultMapper;
5 |
6 | /**
7 | * @author jtremeaux
8 | */
9 | public class FeedSubscriptionMapper extends ResultMapper {
10 | @Override
11 | public FeedSubscriptionDto map(Object[] o) {
12 | int i = 0;
13 | FeedSubscriptionDto dto = new FeedSubscriptionDto();
14 | dto.setId(stringValue(o[i++]));
15 | String feedSubscriptionTitle = stringValue(o[i++]);
16 | dto.setUnreadUserArticleCount(intValue(o[i++]));
17 | dto.setCreateDate(dateValue(o[i++]));
18 | dto.setUserId(stringValue(o[i++]));
19 | dto.setFeedId(stringValue(o[i++]));
20 | String feedTitle = stringValue(o[i++]);
21 | dto.setFeedSubscriptionTitle(feedSubscriptionTitle != null ? feedSubscriptionTitle : feedTitle);
22 | dto.setFeedTitle(feedTitle);
23 | dto.setFeedRssUrl(stringValue(o[i++]));
24 | dto.setFeedUrl(stringValue(o[i++]));
25 | dto.setFeedDescription(stringValue(o[i++]));
26 | dto.setCategoryId(stringValue(o[i++]));
27 | dto.setCategoryParentId(stringValue(o[i++]));
28 | dto.setCategoryName(stringValue(o[i++]));
29 | Boolean folded = booleanValue(o[i++]);
30 | dto.setCategoryFolded(folded != null ? folded : false);
31 | dto.setSynchronizationFailCount(((Number) o[i]).intValue());
32 |
33 | return dto;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/mapper/JobEventMapper.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa.mapper;
2 |
3 | import com.sismics.reader.core.dao.jpa.dto.JobEventDto;
4 | import com.sismics.util.jpa.ResultMapper;
5 |
6 | /**
7 | * @author jtremeaux
8 | */
9 | public class JobEventMapper extends ResultMapper {
10 | @Override
11 | public JobEventDto map(Object[] o) {
12 | int i = 0;
13 | JobEventDto dto = new JobEventDto();
14 | dto.setId(stringValue(o[i++]));
15 | dto.setName(stringValue(o[i++]));
16 | dto.setValue(stringValue(o[i]));
17 |
18 | return dto;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/mapper/JobMapper.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa.mapper;
2 |
3 | import com.sismics.reader.core.dao.jpa.dto.JobDto;
4 | import com.sismics.util.jpa.ResultMapper;
5 |
6 | import java.sql.Timestamp;
7 |
8 | /**
9 | * @author jtremeaux
10 | */
11 | public class JobMapper extends ResultMapper {
12 | @Override
13 | public JobDto map(Object[] o) {
14 | int i = 0;
15 | JobDto dto = new JobDto();
16 | dto.setId(stringValue(o[i++]));
17 | dto.setName(stringValue(o[i++]));
18 | dto.setUserId(stringValue(o[i++]));
19 | Timestamp createTimestamp = (Timestamp) o[i++];
20 | if (createTimestamp != null) {
21 | dto.setCreateTimestamp(createTimestamp.getTime());
22 | }
23 | Timestamp startTimestamp = (Timestamp) o[i++];
24 | if (startTimestamp != null) {
25 | dto.setStartTimestamp(startTimestamp.getTime());
26 | }
27 | Timestamp endTimestamp = (Timestamp) o[i];
28 | if (endTimestamp != null) {
29 | dto.setEndTimestamp(endTimestamp.getTime());
30 | }
31 |
32 | return dto;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/dao/jpa/mapper/UserMapper.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa.mapper;
2 |
3 | import com.sismics.reader.core.dao.jpa.dto.UserDto;
4 | import com.sismics.util.jpa.ResultMapper;
5 |
6 | import java.sql.Timestamp;
7 |
8 | /**
9 | * @author jtremeaux
10 | */
11 | public class UserMapper extends ResultMapper {
12 | @Override
13 | public UserDto map(Object[] o) {
14 | int i = 0;
15 | UserDto dto = new UserDto();
16 | dto.setId(stringValue(o[i++]));
17 | dto.setUsername(stringValue(o[i++]));
18 | dto.setEmail(stringValue(o[i++]));
19 | dto.setCreateTimestamp(((Timestamp) o[i++]).getTime());
20 | dto.setLocaleId(stringValue(o[i]));
21 |
22 | return dto;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/event/ArticleCreatedAsyncEvent.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.event;
2 |
3 | import java.util.List;
4 |
5 | import com.google.common.base.Objects;
6 | import com.sismics.reader.core.model.jpa.Article;
7 |
8 | /**
9 | * New articles created event.
10 | *
11 | * @author bgamard
12 | */
13 | public class ArticleCreatedAsyncEvent {
14 | /**
15 | * List of newly created articles.
16 | */
17 | private List articleList;
18 |
19 | /**
20 | * Getter of articleList.
21 | *
22 | * @return articleList
23 | */
24 | public List getArticleList() {
25 | return articleList;
26 | }
27 |
28 | /**
29 | * Setter of articleList.
30 | *
31 | * @param articleList articleList
32 | */
33 | public void setArticleList(List articleList) {
34 | this.articleList = articleList;
35 | }
36 |
37 | @Override
38 | public String toString() {
39 | return Objects.toStringHelper(this)
40 | .add("articles", (articleList != null ? articleList.size() : "0") + " articles")
41 | .toString();
42 | }
43 | }
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/event/ArticleDeletedAsyncEvent.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.event;
2 |
3 | import com.google.common.base.Objects;
4 | import com.sismics.reader.core.model.jpa.Article;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * Articles deleted event.
10 | *
11 | * @author bgamard
12 | */
13 | public class ArticleDeletedAsyncEvent {
14 | /**
15 | * List of deleted articles.
16 | */
17 | private List articleList;
18 |
19 | /**
20 | * Getter of articleList.
21 | *
22 | * @return articleList
23 | */
24 | public List getArticleList() {
25 | return articleList;
26 | }
27 |
28 | /**
29 | * Setter of articleList.
30 | *
31 | * @param articleList articleList
32 | */
33 | public void setArticleList(List articleList) {
34 | this.articleList = articleList;
35 | }
36 |
37 | @Override
38 | public String toString() {
39 | return Objects.toStringHelper(this)
40 | .add("articles", (articleList != null ? articleList.size() : "0") + " articles")
41 | .toString();
42 | }
43 | }
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/event/ArticleUpdatedAsyncEvent.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.event;
2 |
3 | import java.util.List;
4 |
5 | import com.google.common.base.Objects;
6 | import com.sismics.reader.core.model.jpa.Article;
7 |
8 | /**
9 | * Articles updated event.
10 | *
11 | * @author bgamard
12 | */
13 | public class ArticleUpdatedAsyncEvent {
14 | /**
15 | * List of updated articles.
16 | */
17 | private List articleList;
18 |
19 | /**
20 | * Getter of articleList.
21 | *
22 | * @return articleList
23 | */
24 | public List getArticleList() {
25 | return articleList;
26 | }
27 |
28 | /**
29 | * Setter of articleList.
30 | *
31 | * @param articleList articleList
32 | */
33 | public void setArticleList(List articleList) {
34 | this.articleList = articleList;
35 | }
36 |
37 | @Override
38 | public String toString() {
39 | return Objects.toStringHelper(this)
40 | .add("articles", (articleList != null ? articleList.size() : "0") + " articles")
41 | .toString();
42 | }
43 | }
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/event/FaviconUpdateRequestedEvent.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.event;
2 |
3 | import com.google.common.base.Objects;
4 | import com.sismics.reader.core.model.jpa.Feed;
5 |
6 | /**
7 | * Event raised on request to update a feed favicon.
8 | *
9 | * @author jtremeaux
10 | */
11 | public class FaviconUpdateRequestedEvent {
12 | /**
13 | * Feed to update.
14 | */
15 | private Feed feed;
16 |
17 | @Override
18 | public String toString() {
19 | return Objects.toStringHelper(this)
20 | .add("feedId", feed.getId())
21 | .toString();
22 | }
23 |
24 | /**
25 | * Getter of feed.
26 | *
27 | * @return feed
28 | */
29 | public Feed getFeed() {
30 | return feed;
31 | }
32 |
33 | /**
34 | * Setter of feed.
35 | *
36 | * @param feed feed
37 | */
38 | public void setFeed(Feed feed) {
39 | this.feed = feed;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/event/PasswordChangedEvent.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.event;
2 |
3 | import com.sismics.reader.core.model.jpa.User;
4 |
5 | /**
6 | * Event raised after the user changes his password.
7 | *
8 | * @author jtremeaux
9 | */
10 | public class PasswordChangedEvent {
11 | /**
12 | * Created user.
13 | */
14 | private User user;
15 |
16 | /**
17 | * Getter of user.
18 | *
19 | * @return user
20 | */
21 | public User getUser() {
22 | return user;
23 | }
24 |
25 | /**
26 | * Setter of user.
27 | *
28 | * @param user user
29 | */
30 | public void setUser(User user) {
31 | this.user = user;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/event/RebuildIndexAsyncEvent.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.event;
2 |
3 | import com.google.common.base.Objects;
4 |
5 | /**
6 | * Rebuild index event.
7 | *
8 | * @author bgamard
9 | */
10 | public class RebuildIndexAsyncEvent {
11 | @Override
12 | public String toString() {
13 | return Objects.toStringHelper(this)
14 | .toString();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/event/SubscriptionImportedEvent.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.event;
2 |
3 | import java.io.File;
4 |
5 | import com.google.common.base.Objects;
6 | import com.sismics.reader.core.model.jpa.User;
7 |
8 | /**
9 | * Event raised on request to import an subscriptions (OPML, Google Takeout) file.
10 | *
11 | * @author jtremeaux
12 | */
13 | public class SubscriptionImportedEvent {
14 | /**
15 | * User requesting the import.
16 | */
17 | private User user;
18 |
19 | /**
20 | * Temporary file to import.
21 | */
22 | private File importFile;
23 |
24 | /**
25 | * Getter of user.
26 | *
27 | * @return user
28 | */
29 | public User getUser() {
30 | return user;
31 | }
32 |
33 | /**
34 | * Setter of user.
35 | *
36 | * @param user user
37 | */
38 | public void setUser(User user) {
39 | this.user = user;
40 | }
41 |
42 | /**
43 | * Getter of importFile.
44 | *
45 | * @return importFile
46 | */
47 | public File getImportFile() {
48 | return importFile;
49 | }
50 |
51 | /**
52 | * Setter of importFile.
53 | *
54 | * @param importFile importFile
55 | */
56 | public void setImportFile(File importFile) {
57 | this.importFile = importFile;
58 | }
59 |
60 | @Override
61 | public String toString() {
62 | return Objects.toStringHelper(this)
63 | .add("user", user)
64 | .add("importFile", importFile)
65 | .toString();
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/event/UserCreatedEvent.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.event;
2 |
3 | import com.google.common.base.Objects;
4 | import com.sismics.reader.core.model.jpa.User;
5 |
6 | /**
7 | * Event raised after the creation of a user.
8 | *
9 | * @author jtremeaux
10 | */
11 | public class UserCreatedEvent {
12 | /**
13 | * Created user.
14 | */
15 | private User user;
16 |
17 | /**
18 | * Getter of user.
19 | *
20 | * @return user
21 | */
22 | public User getUser() {
23 | return user;
24 | }
25 |
26 | /**
27 | * Setter of user.
28 | *
29 | * @param user user
30 | */
31 | public void setUser(User user) {
32 | this.user = user;
33 | }
34 |
35 | @Override
36 | public String toString() {
37 | return Objects.toStringHelper(this)
38 | .add("user", user)
39 | .toString();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/listener/async/ArticleDeletedAsyncListener.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.listener.async;
2 |
3 | import com.google.common.eventbus.Subscribe;
4 | import com.sismics.reader.core.dao.lucene.ArticleDao;
5 | import com.sismics.reader.core.event.ArticleDeletedAsyncEvent;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.text.MessageFormat;
10 |
11 | /**
12 | * Listener on deleted articles.
13 | *
14 | * @author bgamard
15 | */
16 | public class ArticleDeletedAsyncListener {
17 | /**
18 | * Logger.
19 | */
20 | private static final Logger log = LoggerFactory.getLogger(ArticleDeletedAsyncListener.class);
21 |
22 | /**
23 | * Process deleted articles.
24 | *
25 | * @param articlesDeletedAsyncEvent Deleted articles event
26 | */
27 | @Subscribe
28 | public void onArticleDeleted(final ArticleDeletedAsyncEvent articlesDeletedAsyncEvent) throws Exception {
29 | if (log.isInfoEnabled()) {
30 | log.info("Deleted article event: " + articlesDeletedAsyncEvent.toString());
31 | }
32 | long startTime = System.currentTimeMillis();
33 |
34 | // Delete index
35 | ArticleDao articleDao = new ArticleDao();
36 | articleDao.delete(articlesDeletedAsyncEvent.getArticleList());
37 |
38 | long endTime = System.currentTimeMillis();
39 | if (log.isInfoEnabled()) {
40 | log.info(MessageFormat.format("Index deleted in {0}ms", endTime - startTime));
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/listener/async/ArticleUpdatedAsyncListener.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.listener.async;
2 |
3 | import com.google.common.eventbus.Subscribe;
4 | import com.sismics.reader.core.dao.lucene.ArticleDao;
5 | import com.sismics.reader.core.event.ArticleUpdatedAsyncEvent;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.text.MessageFormat;
10 |
11 | /**
12 | * Listener on updated articles.
13 | *
14 | * @author bgamard
15 | */
16 | public class ArticleUpdatedAsyncListener {
17 | /**
18 | * Logger.
19 | */
20 | private static final Logger log = LoggerFactory.getLogger(ArticleUpdatedAsyncListener.class);
21 |
22 | /**
23 | * Process updated articles.
24 | *
25 | * @param articlesUpdatedAsyncEvent Updated articles event
26 | */
27 | @Subscribe
28 | public void onArticleUpdated(final ArticleUpdatedAsyncEvent articlesUpdatedAsyncEvent) throws Exception {
29 | if (log.isInfoEnabled()) {
30 | log.info("Updated article event: " + articlesUpdatedAsyncEvent.toString());
31 | }
32 | long startTime = System.currentTimeMillis();
33 |
34 | // Update index
35 | ArticleDao articleDao = new ArticleDao();
36 | articleDao.update(articlesUpdatedAsyncEvent.getArticleList());
37 |
38 | long endTime = System.currentTimeMillis();
39 | if (log.isInfoEnabled()) {
40 | log.info(MessageFormat.format("Index updated in {0}ms", endTime - startTime));
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/listener/async/RebuildIndexAsyncListener.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.listener.async;
2 |
3 | import com.google.common.eventbus.Subscribe;
4 | import com.sismics.reader.core.dao.lucene.ArticleDao;
5 | import com.sismics.reader.core.event.RebuildIndexAsyncEvent;
6 | import com.sismics.reader.core.model.jpa.Article;
7 | import com.sismics.reader.core.util.TransactionUtil;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import java.util.List;
12 |
13 | /**
14 | * Listener on rebuild index.
15 | *
16 | * @author bgamard
17 | */
18 | public class RebuildIndexAsyncListener {
19 | /**
20 | * Logger.
21 | */
22 | private static final Logger log = LoggerFactory.getLogger(RebuildIndexAsyncListener.class);
23 |
24 | /**
25 | * Rebuild articles index.
26 | *
27 | * @param rebuildIndexAsyncEvent Index rebuild event
28 | */
29 | @Subscribe
30 | public void onArticleCreated(final RebuildIndexAsyncEvent rebuildIndexAsyncEvent) throws Exception {
31 | if (log.isInfoEnabled()) {
32 | log.info("Rebuild index event: " + rebuildIndexAsyncEvent.toString());
33 | }
34 |
35 | // Fetch all articles
36 | TransactionUtil.handle(() -> {
37 | com.sismics.reader.core.dao.jpa.ArticleDao jpaArticleDao = new com.sismics.reader.core.dao.jpa.ArticleDao();
38 | List articleList = jpaArticleDao.findAll();
39 |
40 | // Rebuild index
41 | ArticleDao articleDao = new ArticleDao();
42 | articleDao.rebuildIndex(articleList);
43 | });
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/listener/sync/DeadEventListener.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.listener.sync;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import com.google.common.eventbus.DeadEvent;
7 | import com.google.common.eventbus.Subscribe;
8 |
9 | /**
10 | * Listener for all unprocessed events.
11 | *
12 | * @author jtremeaux
13 | */
14 | public class DeadEventListener {
15 | /**
16 | * Logger.
17 | */
18 | private static final Logger log = LoggerFactory.getLogger(DeadEventListener.class);
19 |
20 | /**
21 | * Process every dead event.
22 | *
23 | * @param deadEvent Catchall event
24 | */
25 | @Subscribe
26 | public void onDeadEvent(DeadEvent deadEvent) {
27 | log.error("Dead event catched: " + deadEvent.toString());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/model/jpa/BaseFunction.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.model.jpa;
2 |
3 | import javax.persistence.Column;
4 | import javax.persistence.Entity;
5 | import javax.persistence.Id;
6 | import javax.persistence.Table;
7 |
8 | import com.google.common.base.Objects;
9 |
10 | /**
11 | * Base function entity.
12 | *
13 | * @author jtremeaux
14 | */
15 | @Entity
16 | @Table(name = "T_BASE_FUNCTION")
17 | public class BaseFunction {
18 | /**
19 | * Base function ID (ex: "ADMIN").
20 | */
21 | @Id
22 | @Column(name = "BAF_ID_C", length = 10)
23 | private String id;
24 |
25 | /**
26 | * Getter of id.
27 | *
28 | * @return id
29 | */
30 | public String getId() {
31 | return id;
32 | }
33 |
34 | /**
35 | * Setter of id.
36 | *
37 | * @param id id
38 | */
39 | public void setId(String id) {
40 | this.id = id;
41 | }
42 |
43 | @Override
44 | public String toString() {
45 | return Objects.toStringHelper(this)
46 | .add("id", id)
47 | .toString();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/model/jpa/Locale.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.model.jpa;
2 |
3 | import javax.persistence.Column;
4 | import javax.persistence.Entity;
5 | import javax.persistence.Id;
6 | import javax.persistence.Table;
7 |
8 | import com.google.common.base.Objects;
9 |
10 | /**
11 | * Locale entity.
12 | *
13 | * @author jtremeaux
14 | */
15 | @Entity
16 | @Table(name = "T_LOCALE")
17 | public class Locale {
18 | /**
19 | * Locale ID (ex: fr_FR).
20 | */
21 | @Id
22 | @Column(name = "LOC_ID_C", length = 10)
23 | private String id;
24 |
25 | /**
26 | * Getter of id.
27 | *
28 | * @return id
29 | */
30 | public String getId() {
31 | return id;
32 | }
33 |
34 | /**
35 | * Setter of id.
36 | *
37 | * @param id id
38 | */
39 | public void setId(String id) {
40 | this.id = id;
41 | }
42 |
43 | @Override
44 | public String toString() {
45 | return Objects.toStringHelper(this)
46 | .add("id", id)
47 | .toString();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/util/EntityManagerUtil.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.util;
2 |
3 | import com.sismics.util.context.ThreadLocalContext;
4 |
5 | /**
6 | * Entity manager utils.
7 | *
8 | * @author jtremeaux
9 | */
10 | public class EntityManagerUtil {
11 | /**
12 | * Flush the entity manager session.
13 | */
14 | public static void flush() {
15 | ThreadLocalContext.get().getEntityManager().flush();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/util/StreamUtil.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.util;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.io.PushbackInputStream;
6 | import java.util.zip.GZIPInputStream;
7 |
8 | /**
9 | * Stream utilities.
10 | *
11 | * @author bgamard
12 | */
13 | public class StreamUtil {
14 |
15 | /**
16 | * Detects if the stream is gzipped, and returns a uncompressed stream according to this.
17 | *
18 | * @param is InputStream
19 | * @return InputStream
20 | */
21 | public static InputStream detectGzip(InputStream is) throws IOException {
22 | PushbackInputStream pb = new PushbackInputStream(is, 2);
23 | byte [] signature = new byte[2];
24 | pb.read(signature);
25 | pb.unread(signature);
26 | if(signature[0] == (byte) GZIPInputStream.GZIP_MAGIC && signature[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8)) {
27 | return new GZIPInputStream(pb);
28 | } else {
29 | return pb;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/util/UserUtil.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.util;
2 |
3 | import com.sismics.reader.core.model.jpa.User;
4 |
5 | /**
6 | * Utilitaires sur les utilisateurs.
7 | *
8 | * @author jtremeaux
9 | */
10 | public class UserUtil {
11 | /**
12 | * Retourne the user's username.
13 | *
14 | * @param user User
15 | * @return User name
16 | */
17 | public static String getUserName(User user) {
18 | return user.getUsername();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/util/jpa/SortCriteria.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.util.jpa;
2 |
3 | /**
4 | * Sort criteria of a query.
5 | *
6 | * @author jtremeaux
7 | */
8 | public class SortCriteria {
9 | /**
10 | * Index of the column to sort (first is 0).
11 | */
12 | private int column;
13 |
14 | /**
15 | * Sort in increasing order (or else decreasing).
16 | */
17 | private boolean asc = true;
18 |
19 | private String sortQuery;
20 |
21 | /**
22 | * Constructor of sortCriteria.
23 | */
24 | public SortCriteria(String sortQuery) {
25 | this.sortQuery = sortQuery;
26 | }
27 |
28 | /**
29 | * Constructor of sortCriteria.
30 | */
31 | public SortCriteria(Integer column, Boolean asc) {
32 | if (column != null) {
33 | this.column = column;
34 | }
35 | if (asc != null) {
36 | this.asc = asc;
37 | }
38 | }
39 |
40 | public String getSortQuery() {
41 | return sortQuery;
42 | }
43 |
44 | public int getColumn() {
45 | return column;
46 | }
47 |
48 | public boolean isAsc() {
49 | return asc;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/reader/core/util/sanitizer/TextSanitizer.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.util.sanitizer;
2 |
3 | import java.util.regex.Pattern;
4 |
5 | import org.owasp.html.HtmlPolicyBuilder;
6 | import org.owasp.html.PolicyFactory;
7 |
8 | /**
9 | * Sanitize some HTML text contents. Removes all elements, converts HTML entities to unicode.
10 | *
11 | * @author jtremeaux
12 | */
13 | public class TextSanitizer {
14 | private final static PolicyFactory policy = new HtmlPolicyBuilder().toFactory();
15 | private final static Pattern TAG_PATTERN = Pattern.compile("<.+>");
16 |
17 | /**
18 | * Sanitize title contents.
19 | *
20 | * @param html HTML to sanitize
21 | * @return Sanitized HTML
22 | */
23 | public static String sanitize(String html) {
24 | final String safeHtml = policy.sanitize(html);
25 | return TAG_PATTERN.matcher(safeHtml).replaceAll("");
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/util/MessageUtil.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util;
2 |
3 | import java.text.MessageFormat;
4 | import java.util.Locale;
5 | import java.util.MissingResourceException;
6 | import java.util.ResourceBundle;
7 |
8 | /**
9 | * Message utilities.
10 | *
11 | * @author jtremeaux
12 | */
13 | public class MessageUtil {
14 | /**
15 | * Returns a message formated in the specified locale.
16 | * Returns **key** if no message is set for this key.
17 | *
18 | * @param locale Locale
19 | * @param key Message key
20 | * @param args Arguments of the message
21 | * @return Formated message
22 | */
23 | public static String getMessage(Locale locale, String key, Object... args) {
24 | ResourceBundle resources = ResourceBundle.getBundle("messages", locale);
25 | String message = null;
26 | try {
27 | message = resources.getString(key);
28 | } catch (MissingResourceException e) {
29 | message = "**" + key + "**";
30 | }
31 | return MessageFormat.format(message, args);
32 | }
33 |
34 | /**
35 | * Returns the resource bundle containing messages for the locale.
36 | *
37 | * @param locale Locale to use
38 | * @return Resource bundle
39 | */
40 | public static ResourceBundle getMessage(Locale locale) {
41 | return ResourceBundle.getBundle("messages", locale);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/util/adblock/Helper.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util.adblock;
2 |
3 | import java.io.File;
4 | import java.net.URL;
5 | import java.nio.file.Files;
6 | import java.nio.file.Path;
7 | import java.nio.file.Paths;
8 | import java.util.TimerTask;
9 |
10 | import org.slf4j.Logger;
11 | import org.slf4j.LoggerFactory;
12 |
13 | import com.google.common.base.Charsets;
14 | import com.google.common.io.Resources;
15 |
16 | public class Helper {
17 |
18 | private static final Logger log = LoggerFactory.getLogger(Helper.class);
19 |
20 | private JSEngine js;
21 |
22 | public Helper(JSEngine js) {
23 | this.js = js;
24 | }
25 |
26 | public void log(Object msg) {
27 | log.debug(msg.toString());
28 | }
29 |
30 | public void load(String path) throws Exception {
31 | URL url = Resources.getResource("adblock" + File.separator + "js" + File.separator + path);
32 | js.evaluate(Resources.toString(url, Charsets.UTF_8));
33 | }
34 |
35 | public boolean fileExists(String stringPath) {
36 | Path path = Paths.get(stringPath);
37 | return Files.exists(path);
38 | }
39 |
40 | public boolean canAutoupdate() {
41 | return true;
42 | }
43 |
44 | public TimerTask timerTask(final Runnable runnable) {
45 | return new TimerTask() {
46 | @Override
47 | public void run() {
48 | runnable.run();
49 | }
50 | };
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/util/adblock/JSEngine.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util.adblock;
2 |
3 | import javax.script.ScriptEngine;
4 | import javax.script.ScriptEngineManager;
5 | import javax.script.ScriptException;
6 |
7 | public class JSEngine {
8 |
9 | private ScriptEngine engine;
10 |
11 | public JSEngine() {
12 | ScriptEngineManager manager = new ScriptEngineManager();
13 | engine = manager.getEngineByName("JavaScript");
14 | }
15 |
16 | public Object evaluate(String script) throws ScriptException {
17 | return engine.eval(script);
18 | }
19 |
20 | public void put(String key, Object value) {
21 | engine.put(key, value);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/util/adblock/Subscription.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of Adblock Plus ,
3 | * Copyright (C) 2006-2013 Eyeo GmbH
4 | *
5 | * Adblock Plus is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License version 3 as
7 | * published by the Free Software Foundation.
8 | *
9 | * Adblock Plus is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with Adblock Plus. If not, see .
16 | */
17 |
18 | package com.sismics.util.adblock;
19 |
20 | public class Subscription {
21 | public String title;
22 | public String specialization;
23 | public String url;
24 | public String homepage;
25 | public String[] prefixes;
26 | public String author;
27 | }
28 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/util/cert/TrustAllManager.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util.cert;
2 |
3 | import javax.net.ssl.X509TrustManager;
4 | import java.security.cert.CertificateException;
5 | import java.security.cert.X509Certificate;
6 |
7 | /**
8 | * A trust manager that trusts all certificates (unsecure).
9 | *
10 | * @author jtremeaux
11 | */
12 | public class TrustAllManager implements X509TrustManager {
13 | @Override
14 | public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
15 | // NOP
16 | }
17 |
18 | @Override
19 | public void checkServerTrusted(X509Certificate[] certs, String authType) {
20 | // NOP
21 | }
22 |
23 | @Override
24 | public X509Certificate[] getAcceptedIssuers() {
25 | return null;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/util/jpa/SessionUtil.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util.jpa;
2 |
3 | import org.hibernate.Session;
4 | import org.hibernate.SessionFactory;
5 | import org.hibernate.ejb.HibernateEntityManagerFactory;
6 |
7 | /**
8 | * Hibernate session utilities.
9 | *
10 | * @author jtremeaux
11 | */
12 | public final class SessionUtil {
13 | /**
14 | * Private constructor.
15 | */
16 | private SessionUtil() {
17 | }
18 |
19 | /**
20 | * Returns an instance of the current session.
21 | *
22 | * @return Instance of the current session
23 | */
24 | public static Session getCurrentSession() {
25 | SessionFactory sessionFactory = ((HibernateEntityManagerFactory) EMF.get()).getSessionFactory();
26 | return sessionFactory.getCurrentSession();
27 | }
28 | }
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/util/jpa/filter/FilterColumn.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util.jpa.filter;
2 |
3 | /**
4 | * Filter to apply on a column.
5 | *
6 | * @author jtremeaux
7 | */
8 | public abstract class FilterColumn {
9 | /**
10 | * Column to filter.
11 | */
12 | protected String column;
13 |
14 | /**
15 | * Filter expression to apply.
16 | */
17 | protected String filter;
18 |
19 | public FilterColumn(String column, String filter) {
20 | this.column = column;
21 | this.filter = filter;
22 | }
23 |
24 | public String getColumn() {
25 | return column;
26 | }
27 |
28 | public String getFilter() {
29 | return filter;
30 | }
31 |
32 | public abstract String getPredicate();
33 |
34 | public abstract Object getParamValue();
35 |
36 | public String getParamName() {
37 | return "filtercolumn_" + column;
38 | }
39 |
40 | public boolean hasParam() {
41 | return column != null;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/util/jpa/filter/FilterCriteria.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util.jpa.filter;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * Filtering criteria of a query.
8 | *
9 | * @author jtremeaux
10 | */
11 | public class FilterCriteria {
12 | /**
13 | * Columns to sort.
14 | */
15 | private List filterColumnList = new ArrayList();
16 |
17 | /**
18 | * Constructor of SortCriteria.
19 | *
20 | * @param filterColumnList List of sort columns
21 | */
22 | public FilterCriteria(List filterColumnList) {
23 | this.filterColumnList = filterColumnList;
24 | }
25 |
26 | public List getFilterColumnList() {
27 | return filterColumnList;
28 | }
29 | }
--------------------------------------------------------------------------------
/reader-core/src/main/java/com/sismics/util/mime/MimeType.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util.mime;
2 |
3 | /**
4 | * A collection of MIME types.
5 | *
6 | * @author jtremeaux
7 | */
8 | public class MimeType {
9 |
10 | public static final String IMAGE_X_ICON = "image/x-icon";
11 |
12 | public static final String IMAGE_PNG = "image/png";
13 |
14 | public static final String IMAGE_JPEG = "image/jpeg";
15 |
16 | public static final String IMAGE_GIF = "image/gif";
17 |
18 | public static final String APPLICATION_ZIP = "application/zip";
19 | }
20 |
--------------------------------------------------------------------------------
/reader-core/src/main/resources/META-INF/persistence.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | org.hibernate.ejb.HibernatePersistence
8 |
9 | com.sismics.reader.core.model.jpa.Article
10 | com.sismics.reader.core.model.jpa.AuthenticationToken
11 | com.sismics.reader.core.model.jpa.BaseFunction
12 | com.sismics.reader.core.model.jpa.Category
13 | com.sismics.reader.core.model.jpa.Config
14 | com.sismics.reader.core.model.jpa.Feed
15 | com.sismics.reader.core.model.jpa.FeedSubscription
16 | com.sismics.reader.core.model.jpa.FeedSynchronization
17 | com.sismics.reader.core.model.jpa.Job
18 | com.sismics.reader.core.model.jpa.JobEvent
19 | com.sismics.reader.core.model.jpa.Locale
20 | com.sismics.reader.core.model.jpa.User
21 | com.sismics.reader.core.model.jpa.UserArticle
22 | com.sismics.reader.core.model.jpa.RoleBaseFunction
23 |
24 |
--------------------------------------------------------------------------------
/reader-core/src/main/resources/db/update/dbupdate-001-0.sql:
--------------------------------------------------------------------------------
1 | alter table T_FEED add column FED_RSSBASEURI_C varchar(2000);
2 | alter table T_ARTICLE add column ART_BASEURI_C varchar(2000);
3 | create cached table T_JOB (JOB_ID_C varchar(36) not null, JOB_IDUSER_C varchar(36), JOB_NAME_C varchar(50) not null, JOB_CREATEDATE_D datetime not null, JOB_STARTDATE_D datetime, JOB_ENDDATE_D datetime, JOB_DELETEDATE_D datetime, primary key (JOB_ID_C));
4 | create cached table T_JOB_EVENT ( JOE_ID_C varchar(36) not null, JOE_IDJOB_C varchar(36), JOE_NAME_C varchar(50) not null, JOE_VALUE_C varchar(250), JOE_CREATEDATE_D datetime not null, JOE_DELETEDATE_D datetime, primary key (JOE_ID_C));
5 | alter table T_JOB add constraint FK_JOB_IDUSER_C foreign key (JOB_IDUSER_C) references T_USER (USE_ID_C) on delete restrict on update restrict;
6 | alter table T_JOB_EVENT add constraint FK_JOE_IDJOB_C foreign key (JOE_IDJOB_C) references T_JOB (JOB_ID_C) on delete restrict on update restrict;
7 | create index IDX_ART_PUBLICATIONDATE_D on T_ARTICLE (ART_PUBLICATIONDATE_D, ART_ID_C);
8 | create index IDX_USA_STARREDDATE_D on T_USER_ARTICLE (USA_STARREDDATE_D, USA_ID_C);
9 | update T_CONFIG set CFG_VALUE_C='1' where CFG_ID_C='DB_VERSION';
10 |
--------------------------------------------------------------------------------
/reader-core/src/main/resources/db/update/dbupdate-002-0.sql:
--------------------------------------------------------------------------------
1 | alter table T_USER add column USE_NARROWARTICLE_B bit default 0 not null;
2 | update T_CONFIG set CFG_VALUE_C='2' where CFG_ID_C='DB_VERSION';
3 |
--------------------------------------------------------------------------------
/reader-core/src/main/resources/db/update/dbupdate-003-0.sql:
--------------------------------------------------------------------------------
1 | alter table T_FEED_SUBSCRIPTION add column FES_UNREADCOUNT_N int default 0 not null;
2 | update T_FEED_SUBSCRIPTION set FES_UNREADCOUNT_N=(select count(a.ART_ID_C) from T_USER_ARTICLE ua join T_ARTICLE a on ua.USA_IDARTICLE_C = a.ART_ID_C where a.ART_IDFEED_C = FES_IDFEED_C and a.ART_DELETEDATE_D is null and ua.USA_READDATE_D is null and ua.USA_DELETEDATE_D is null and ua.USA_IDUSER_C = FES_IDUSER_C);
3 | update T_CONFIG set CFG_VALUE_C='3' where CFG_ID_C='DB_VERSION';
4 |
--------------------------------------------------------------------------------
/reader-core/src/main/resources/db/update/dbupdate-004-0.sql:
--------------------------------------------------------------------------------
1 | update T_USER set USE_THEME_C = 'default' where USE_THEME_C = 'default.less';
2 | update T_USER set USE_THEME_C = 'highcontrast' where USE_THEME_C = 'highcontrast.less';
3 | update T_CONFIG set CFG_VALUE_C='4' where CFG_ID_C='DB_VERSION';
4 |
--------------------------------------------------------------------------------
/reader-core/src/main/resources/db/update/dbupdate-005-0.sql:
--------------------------------------------------------------------------------
1 | create index IDX_USA_READDATE_D on T_USER_ARTICLE (USA_READDATE_D, USA_ID_C);
2 | create cached table T_FEED_SYNCHRONIZATION ( FSY_ID_C varchar(36) not null, FSY_IDFEED_C varchar(36) not null, FSY_SUCCESS_B bit not null, FSY_MESSAGE_C longvarchar, FSY_DURATION_N int not null, FSY_CREATEDATE_D datetime not null, primary key (FSY_ID_C) );
3 | alter table T_FEED_SYNCHRONIZATION add constraint FK_FSY_IDFEED_C foreign key (FSY_IDFEED_C) references T_FEED (FED_ID_C) on delete restrict on update restrict;
4 | create index IDX_FSY_CREATEDATE_D on T_FEED_SYNCHRONIZATION (FSY_IDFEED_C, FSY_CREATEDATE_D);
5 | update T_CONFIG set CFG_VALUE_C='5' where CFG_ID_C='DB_VERSION';
6 |
--------------------------------------------------------------------------------
/reader-core/src/main/resources/db/update/dbupdate-006-0.sql:
--------------------------------------------------------------------------------
1 | create index FK_ART_IDFEED_C on T_ARTICLE (ART_IDFEED_C);
2 | create index FK_AUT_IDUSER_C on T_AUTHENTICATION_TOKEN (AUT_IDUSER_C);
3 | create index FK_USA_IDARTICLE_C on T_USER_ARTICLE (USA_IDARTICLE_C);
4 | create index FK_USA_IDUSER_C on T_USER_ARTICLE (USA_IDUSER_C);
5 | create index FK_USE_IDROLE_C on T_USER (USE_IDROLE_C);
6 | create index FK_USE_IDLOCALE_C on T_USER (USE_IDLOCALE_C);
7 | create index FK_RBF_IDBASEFUNCTION_C on T_ROLE_BASE_FUNCTION (RBF_IDBASEFUNCTION_C);
8 | create index FK_RBF_IDROLE_C on T_ROLE_BASE_FUNCTION (RBF_IDROLE_C);
9 | create index FK_JOE_IDJOB_C on T_JOB_EVENT (JOE_IDJOB_C);
10 | create index FK_JOB_IDUSER_C on T_JOB (JOB_IDUSER_C);
11 | create index FK_FES_IDCATEGORY_C on T_FEED_SUBSCRIPTION (FES_IDCATEGORY_C);
12 | create index FK_FES_IDFEED_C on T_FEED_SUBSCRIPTION (FES_IDFEED_C);
13 | create index FK_FES_IDUSER_C on T_FEED_SUBSCRIPTION (FES_IDUSER_C);
14 | create index FK_CAT_IDPARENT_C on T_CATEGORY (CAT_IDPARENT_C);
15 | create index FK_CAT_IDUSER_C on T_CATEGORY (CAT_IDUSER_C);
16 | update T_CONFIG set CFG_VALUE_C='6' where CFG_ID_C='DB_VERSION';
--------------------------------------------------------------------------------
/reader-core/src/main/resources/messages.properties:
--------------------------------------------------------------------------------
1 | reader.export.title={0}''s subscriptions in Sismics Reader
2 |
--------------------------------------------------------------------------------
/reader-core/src/main/resources/messages_fr.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/reader-core/src/test/java/com/sismics/reader/BaseTransactionalTest.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader;
2 |
3 | import javax.persistence.EntityManager;
4 | import javax.persistence.EntityTransaction;
5 |
6 | import org.junit.After;
7 | import org.junit.Before;
8 |
9 | import com.sismics.util.context.ThreadLocalContext;
10 | import com.sismics.util.jpa.EMF;
11 |
12 | /**
13 | * Base class of tests with a transactional context.
14 | *
15 | * @author jtremeaux
16 | */
17 | public abstract class BaseTransactionalTest {
18 | @Before
19 | public void setUp() throws Exception {
20 | // Initialize the entity manager
21 | EntityManager em = EMF.get().createEntityManager();
22 | ThreadLocalContext context = ThreadLocalContext.get();
23 | context.setEntityManager(em);
24 | EntityTransaction tx = em.getTransaction();
25 | tx.begin();
26 | }
27 |
28 | @After
29 | public void tearDown() throws Exception {
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/reader-core/src/test/java/com/sismics/reader/core/dao/file/html/TestFaviconExtractor.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.file.html;
2 |
3 | import com.sismics.reader.core.util.http.ReaderHttpClient;
4 | import org.junit.Test;
5 |
6 | import java.io.InputStream;
7 | import java.net.URL;
8 |
9 | import static junit.framework.Assert.assertTrue;
10 |
11 | /**
12 | * Test of the favicon extractor.
13 | *
14 | * @author jtremeaux
15 | */
16 | public class TestFaviconExtractor {
17 | @Test
18 | public void faviconExtractorSismicsTest() throws Exception {
19 | final FaviconExtractor extractor = new FaviconExtractor("https://www.sismics.com/");
20 | new ReaderHttpClient() {
21 |
22 | @Override
23 | public Void process(InputStream is) throws Exception {
24 | extractor.readPage(is);
25 | return null;
26 | }
27 | }.open(new URL("https://www.sismics.com"));
28 | assertTrue(extractor.getFavicon().contains("/public/img/favicon.png"));
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/reader-core/src/test/java/com/sismics/reader/core/dao/jpa/TestJpa.java:
--------------------------------------------------------------------------------
1 | package com.sismics.reader.core.dao.jpa;
2 |
3 | import com.sismics.reader.BaseTransactionalTest;
4 | import com.sismics.reader.core.model.jpa.User;
5 | import com.sismics.reader.core.util.TransactionUtil;
6 | import org.junit.Test;
7 |
8 | import static junit.framework.Assert.assertEquals;
9 | import static junit.framework.Assert.assertNotNull;
10 |
11 | /**
12 | * Tests the persistance layer.
13 | *
14 | * @author jtremeaux
15 | */
16 | public class TestJpa extends BaseTransactionalTest {
17 | @Test
18 | public void testJpa() throws Exception {
19 | // Create a user
20 | UserDao userDao = new UserDao();
21 | User user = new User();
22 | user.setUsername("username");
23 | user.setEmail("toto@reader.com");
24 | user.setLocaleId("fr_FR");
25 | user.setRoleId("user");
26 | String id = userDao.create(user);
27 |
28 | TransactionUtil.commit();
29 |
30 | // Search a user by his ID
31 | user = userDao.getById(id);
32 | assertNotNull(user);
33 | assertEquals("toto@reader.com", user.getEmail());
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/reader-core/src/test/java/com/sismics/util/TestAdblockUtil.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util;
2 |
3 | import com.sismics.util.adblock.Subscription;
4 | import org.junit.Ignore;
5 | import org.junit.Test;
6 |
7 | @Ignore
8 | public class TestAdblockUtil {
9 |
10 | @Test
11 | public void test() throws Exception {
12 | AdblockUtil adblock = new AdblockUtil();
13 | adblock.start();
14 | Subscription subscription = adblock.offerSubscription();
15 | adblock.setSubscription(subscription);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/reader-core/src/test/java/com/sismics/util/TestCertUtil.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util;
2 |
3 | import com.sismics.reader.core.util.http.ReaderHttpClient;
4 | import com.sismics.util.cert.CertUtil;
5 | import org.junit.Ignore;
6 | import org.junit.Test;
7 |
8 | import java.io.InputStream;
9 | import java.net.URL;
10 |
11 | import static junit.framework.Assert.fail;
12 |
13 | /**
14 | * Test of the certificate utilities.
15 | *
16 | * @author jtremeaux
17 | */
18 | @Ignore
19 | public class TestCertUtil {
20 |
21 | @Test
22 | public void sslFailTest() throws Exception {
23 | // This fails at the time of test, due to Startcom certificate not included in the JDK
24 | // javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed:
25 | // sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
26 | try {
27 | CertUtil.testSsl("lescastcodeurs.com", 443);
28 | fail();
29 | } catch (Exception e) {
30 | // NOP
31 | }
32 | }
33 |
34 | @Test
35 | public void sslTrustAllCertificateTest() throws Exception {
36 | new ReaderHttpClient() {
37 | @Override
38 | public Void process(InputStream is) throws Exception {
39 | return null;
40 | }
41 | }.open(new URL("https://lescastcodeurs.com"));
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/reader-core/src/test/java/com/sismics/util/TestDateUtil.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util;
2 |
3 | import com.sismics.reader.core.dao.file.rss.RssReader;
4 | import org.junit.Test;
5 |
6 | import static junit.framework.Assert.assertEquals;
7 | import static junit.framework.Assert.assertNotNull;
8 |
9 | /**
10 | * Test of the date utilities.
11 | *
12 | * @author jtremeaux
13 | */
14 | public class TestDateUtil {
15 |
16 | @Test
17 | public void guessTimezoneCodeTest() throws Exception {
18 | assertEquals("Thu, 04 APR 2013 20:37:27 +10", DateUtil.guessTimezoneOffset("Thu, 04 APR 2013 20:37:27 AEST"));
19 | }
20 |
21 | @Test
22 | public void parseDateTest() throws Exception {
23 | assertNotNull(DateUtil.parseDate("Fri Jan 06 2017 16:13:28 GMT+0900 (JST)", RssReader.DF_RSS));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/reader-core/src/test/java/com/sismics/util/TestNetworkUtil.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util;
2 |
3 | import org.junit.Ignore;
4 | import org.junit.Test;
5 |
6 | import static junit.framework.Assert.assertTrue;
7 |
8 | /**
9 | * Test of the network utilities.
10 | *
11 | * @author bgamard
12 | */
13 | public class TestNetworkUtil {
14 |
15 | @Test
16 | @Ignore
17 | public void testUpnp() throws Exception {
18 | assertTrue(NetworkUtil.mapTcpPort(4040));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/reader-core/src/test/java/com/sismics/util/TestResourceUtil.java:
--------------------------------------------------------------------------------
1 | package com.sismics.util;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | import static junit.framework.Assert.assertNotNull;
9 | import static junit.framework.Assert.assertTrue;
10 |
11 | /**
12 | * Test of the resource utils.
13 | *
14 | * @author jtremeaux
15 | */
16 | public class TestResourceUtil {
17 |
18 | @Test
19 | public void listFilesTest() throws Exception {
20 | List fileList = ResourceUtil.list(Test.class, "/junit/framework");
21 | assertTrue(fileList.contains("Test.class"));
22 |
23 | fileList = ResourceUtil.list(Test.class, "/junit/framework/");
24 | assertTrue(fileList.contains("Test.class"));
25 |
26 | fileList = ResourceUtil.list(Test.class, "junit/framework/");
27 | assertTrue(fileList.contains("Test.class"));
28 |
29 | fileList = ResourceUtil.list(Test.class, "junit/framework/");
30 | assertTrue(fileList.contains("Test.class"));
31 | }
32 |
33 | @Test
34 | public void loadResourceFileTest() {
35 | Map