/*
* Copyright (c) 2010-2017, b3log.org & hacpai.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.b3log.solo.service;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
import org.b3log.latke.Keys;
import org.b3log.latke.Latkes;
import org.b3log.latke.RuntimeDatabase;
import org.b3log.latke.RuntimeEnv;
import org.b3log.latke.ioc.inject.Inject;
import org.b3log.latke.logging.Level;
import org.b3log.latke.logging.Logger;
import org.b3log.latke.model.Role;
import org.b3log.latke.model.User;
import org.b3log.latke.plugin.PluginManager;
import org.b3log.latke.repository.RepositoryException;
import org.b3log.latke.repository.Transaction;
import org.b3log.latke.repository.jdbc.util.JdbcRepositories;
import org.b3log.latke.repository.jdbc.util.JdbcRepositories.CreateTableResult;
import org.b3log.latke.service.LangPropsService;
import org.b3log.latke.service.ServiceException;
import org.b3log.latke.service.annotation.Service;
import org.b3log.latke.urlfetch.HTTPRequest;
import org.b3log.latke.urlfetch.URLFetchService;
import org.b3log.latke.urlfetch.URLFetchServiceFactory;
import org.b3log.latke.util.Ids;
import org.b3log.latke.util.MD5;
import org.b3log.latke.util.freemarker.Templates;
import org.b3log.solo.SoloServletListener;
import org.b3log.solo.model.*;
import org.b3log.solo.model.Option.DefaultPreference;
import org.b3log.solo.repository.*;
import org.b3log.solo.util.Comments;
import org.b3log.solo.util.Skins;
import org.b3log.solo.util.Thumbnails;
import org.b3log.solo.util.TimeZones;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import javax.servlet.ServletContext;
import java.net.URL;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
* Solo initialization service.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.5.2.11, Nov 8, 2016
* @since 0.4.0
*/
@Service
public class InitService {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(InitService.class.getName());
/**
* Statistic repository.
*/
@Inject
private StatisticRepository statisticRepository;
/**
* Option repository.
*/
@Inject
private OptionRepository optionRepository;
/**
* User repository.
*/
@Inject
private UserRepository userRepository;
/**
* Tag-Article repository.
*/
@Inject
private TagArticleRepository tagArticleRepository;
/**
* Archive date repository.
*/
@Inject
private ArchiveDateRepository archiveDateRepository;
/**
* Archive date-Article repository.
*/
@Inject
private ArchiveDateArticleRepository archiveDateArticleRepository;
/**
* Tag repository.
*/
@Inject
private TagRepository tagRepository;
/**
* Article repository.
*/
@Inject
private ArticleRepository articleRepository;
/**
* Comment repository.
*/
@Inject
private CommentRepository commentRepository;
/**
* Link repository.
*/
@Inject
private LinkRepository linkRepository;
/**
* Maximum count of initialization.
*/
private static final int MAX_RETRIES_CNT = 3;
/**
* Initialized time zone id.
*/
private static final String INIT_TIME_ZONE_ID = "Asia/Shanghai";
/**
* Language service.
*/
@Inject
private LangPropsService langPropsService;
/**
* Plugin manager.
*/
@Inject
private PluginManager pluginManager;
/**
* Determines Solo had been initialized.
*
* @return {@code true} if it had been initialized, {@code false} otherwise
*/
// XXX: to find a better way (isInited)?
public boolean isInited() {
try {
final JSONObject admin = userRepository.getAdmin();
return null != admin;
} catch (final RepositoryException e) {
LOGGER.log(Level.WARN, "Solo has not been initialized");
return false;
}
}
/**
* Initializes Solo.
*
* <p>
* Initializes the followings in sequence:
* <ol>
* <li>Statistic</li>
* <li>Preference</li>
* <li>Administrator</li>
* </ol>
* </p>
*
* <p>
* We will try to initialize Solo 3 times at most.
* </p>
*
* <p>
* Posts "Hello World!" article and its comment while Solo initialized.
* </p>
*
* @param requestJSONObject the specified request json object, for example, <pre>
* {
* "userName": "",
* "userEmail": "",
* "userPassword": "", // Unhashed
* }
* </pre>
*
* @throws ServiceException service exception
*/
public void init(final JSONObject requestJSONObject) throws ServiceException {
if (isInited()) {
return;
}
final RuntimeEnv runtimeEnv = Latkes.getRuntimeEnv();
if (RuntimeEnv.LOCAL == runtimeEnv) {
LOGGER.log(Level.INFO, "Solo is running on [" + runtimeEnv + "] environment, database [{0}], creates "
+ "all tables", Latkes.getRuntimeDatabase());
if (RuntimeDatabase.H2 == Latkes.getRuntimeDatabase()) {
String dataDir = Latkes.getLocalProperty("jdbc.URL");
dataDir = dataDir.replace("~", System.getProperty("user.home"));
LOGGER.log(Level.INFO, "YOUR DATA will be stored in directory [" + dataDir + "], "
+ "please pay more attention to it~");
}
final List<CreateTableResult> createTableResults = JdbcRepositories.initAllTables();
for (final CreateTableResult createTableResult : createTableResults) {
LOGGER.log(Level.DEBUG, "Create table result[tableName={0}, isSuccess={1}]",
createTableResult.getName(), createTableResult.isSuccess());
}
}
int retries = MAX_RETRIES_CNT;
while (true) {
final Transaction transaction = userRepository.beginTransaction();
try {
final JSONObject statistic = statisticRepository.get(Statistic.STATISTIC);
if (null == statistic) {
initStatistic();
initPreference(requestJSONObject);
initReplyNotificationTemplate();
initAdmin(requestJSONObject);
initLink();
}
transaction.commit();
break;
} catch (final Exception e) {
if (0 == retries) {
LOGGER.log(Level.ERROR, "Initialize Solo error", e);
throw new ServiceException("Initailize Solo error: " + e.getMessage());
}
// Allow retry to occur
--retries;
LOGGER.log(Level.WARN, "Retrying to init Solo[retries={0}]", retries);
} finally {
if (transaction.isActive()) {
transaction.rollback();
}
}
}
final Transaction transaction = userRepository.beginTransaction();
try {
helloWorld();
transaction.commit();
} catch (final Exception e) {
if (transaction.isActive()) {
transaction.rollback();
}
LOGGER.log(Level.ERROR, "Hello World error?!", e);
}
try {
final URLFetchService urlFetchService = URLFetchServiceFactory.getURLFetchService();
final HTTPRequest req = new HTTPRequest();
req.setURL(new URL(Latkes.getServePath() + "/blog/symphony/user"));
urlFetchService.fetch(req);
} catch (final Exception e) {
LOGGER.log(Level.TRACE, "Sync account failed");
}
pluginManager.load();
}
/**
* Publishes the first article "Hello World" and the first comment with the specified locale.
*
* @throws Exception exception
*/
private void helloWorld() throws Exception {
final JSONObject article = new JSONObject();
article.put(Article.ARTICLE_TITLE, langPropsService.get("helloWorld.title"));
final String content = langPropsService.get("helloWorld.content");
article.put(Article.ARTICLE_ABSTRACT, content);
article.put(Article.ARTICLE_CONTENT, content);
article.put(Article.ARTICLE_TAGS_REF, "Solo");
article.put(Article.ARTICLE_PERMALINK, "/hello-solo");
article.put(Article.ARTICLE_IS_PUBLISHED, true);
article.put(Article.ARTICLE_HAD_BEEN_PUBLISHED, true);
article.put(Article.ARTICLE_SIGN_ID, "1");
article.put(Article.ARTICLE_COMMENT_COUNT, 1);
article.put(Article.ARTICLE_VIEW_COUNT, 0);
final Date date = new Date();
final JSONObject admin = userRepository.getAdmin();
final String authorEmail = admin.optString(User.USER_EMAIL);
article.put(Article.ARTICLE_CREATE_DATE, date);
article.put(Article.ARTICLE_UPDATE_DATE, date);
article.put(Article.ARTICLE_PUT_TOP, false);
article.put(Article.ARTICLE_RANDOM_DOUBLE, Math.random());
article.put(Article.ARTICLE_AUTHOR_EMAIL, authorEmail);
article.put(Article.ARTICLE_COMMENTABLE, true);
article.put(Article.ARTICLE_VIEW_PWD, "");
article.put(Article.ARTICLE_EDITOR_TYPE, DefaultPreference.DEFAULT_EDITOR_TYPE);
final String articleId = addHelloWorldArticle(article);
final JSONObject comment = new JSONObject();
comment.put(Keys.OBJECT_ID, articleId);
comment.put(Comment.COMMENT_NAME, "Daniel");
comment.put(Comment.COMMENT_EMAIL, "dl88250@gmail.com");
comment.put(Comment.COMMENT_URL, "https://hacpai.com/member/88250");
comment.put(Comment.COMMENT_CONTENT, langPropsService.get("helloWorld.comment.content"));
comment.put(Comment.COMMENT_ORIGINAL_COMMENT_ID, "");
comment.put(Comment.COMMENT_ORIGINAL_COMMENT_NAME, "");
comment.put(Comment.COMMENT_THUMBNAIL_URL, Thumbnails.GRAVATAR + "59a5e8209c780307dbe9c9ba728073f5??s=60&r=G");
comment.put(Comment.COMMENT_DATE, date);
comment.put(Comment.COMMENT_ON_ID, articleId);
comment.put(Comment.COMMENT_ON_TYPE, Article.ARTICLE);
final String commentId = Ids.genTimeMillisId();
comment.put(Keys.OBJECT_ID, commentId);
final String commentSharpURL = Comments.getCommentSharpURLForArticle(article, commentId);
comment.put(Comment.COMMENT_SHARP_URL, commentSharpURL);
commentRepository.add(comment);
LOGGER.info("Hello World!");
}
/**
* Adds the specified "Hello World" article.
*
* @param article the specified "Hello World" article
* @return generated article id
* @throws RepositoryException repository exception
*/
private String addHelloWorldArticle(final JSONObject article) throws RepositoryException {
final String ret = Ids.genTimeMillisId();
try {
article.put(Keys.OBJECT_ID, ret);
// Step 1: Add tags
final String tagsString = article.optString(Article.ARTICLE_TAGS_REF);
final String[] tagTitles = tagsString.split(",");
final JSONArray tags = tag(tagTitles, article);
// Step 2: Add tag-article relations
addTagArticleRelation(tags, article);
// Step 3: Inc blog article and comment count statictis
final JSONObject statistic = statisticRepository.get(Statistic.STATISTIC);
statistic.put(Statistic.STATISTIC_BLOG_ARTICLE_COUNT, 1);
statistic.put(Statistic.STATISTIC_PUBLISHED_ARTICLE_COUNT, 1);
statistic.put(Statistic.STATISTIC_PUBLISHED_BLOG_COMMENT_COUNT, 1);
statistic.put(Statistic.STATISTIC_BLOG_COMMENT_COUNT, 1);
statisticRepository.update(Statistic.STATISTIC, statistic);
// Step 4: Add archive date-article relations
archiveDate(article);
// Step 5: Add article
articleRepository.add(article);
// Step 6: Update admin user for article statistic
final JSONObject admin = userRepository.getAdmin();
admin.put(UserExt.USER_ARTICLE_COUNT, 1);
admin.put(UserExt.USER_PUBLISHED_ARTICLE_COUNT, 1);
userRepository.update(admin.optString(Keys.OBJECT_ID), admin);
} catch (final RepositoryException e) {
LOGGER.log(Level.ERROR, "Adds an article failed", e);
throw new RepositoryException(e);
}
return ret;
}
/**
* Archive the create date with the specified article.
*
* @param article the specified article, for example, <pre>
* {
* ....,
* "oId": "",
* "articleCreateDate": java.util.Date,
* ....
* }
* </pre>
*
* @throws RepositoryException repository exception
*/
public void archiveDate(final JSONObject article) throws RepositoryException {
final Date createDate = (Date) article.opt(Article.ARTICLE_CREATE_DATE);
final String createDateString = DateFormatUtils.format(createDate, "yyyy/MM");
final JSONObject archiveDate = new JSONObject();
try {
archiveDate.put(ArchiveDate.ARCHIVE_TIME, DateUtils.parseDate(createDateString, new String[]{"yyyy/MM"}).getTime());
archiveDate.put(ArchiveDate.ARCHIVE_DATE_ARTICLE_COUNT, 1);
archiveDate.put(ArchiveDate.ARCHIVE_DATE_PUBLISHED_ARTICLE_COUNT, 1);
archiveDateRepository.add(archiveDate);
} catch (final ParseException e) {
LOGGER.log(Level.ERROR, e.getMessage(), e);
throw new RepositoryException(e);
}
final JSONObject archiveDateArticleRelation = new JSONObject();
archiveDateArticleRelation.put(ArchiveDate.ARCHIVE_DATE + "_" + Keys.OBJECT_ID, archiveDate.optString(Keys.OBJECT_ID));
archiveDateArticleRelation.put(Article.ARTICLE + "_" + Keys.OBJECT_ID, article.optString(Keys.OBJECT_ID));
archiveDateArticleRepository.add(archiveDateArticleRelation);
}
/**
* Adds relation of the specified tags and article.
*
* @param tags the specified tags
* @param article the specified article
* @throws RepositoryException repository exception
*/
private void addTagArticleRelation(final JSONArray tags, final JSONObject article) throws RepositoryException {
for (int i = 0; i < tags.length(); i++) {
final JSONObject tag = tags.optJSONObject(i);
final JSONObject tagArticleRelation = new JSONObject();
tagArticleRelation.put(Tag.TAG + "_" + Keys.OBJECT_ID, tag.optString(Keys.OBJECT_ID));
tagArticleRelation.put(Article.ARTICLE + "_" + Keys.OBJECT_ID, article.optString(Keys.OBJECT_ID));
tagArticleRepository.add(tagArticleRelation);
}
}
/**
* Tags the specified article with the specified tag titles.
*
* @param tagTitles the specified tag titles
* @param article the specified article
* @return an array of tags
* @throws RepositoryException repository exception
*/
private JSONArray tag(final String[] tagTitles, final JSONObject article) throws RepositoryException {
final JSONArray ret = new JSONArray();
for (int i = 0; i < tagTitles.length; i++) {
final String tagTitle = tagTitles[i].trim();
final JSONObject tag = new JSONObject();
LOGGER.log(Level.TRACE, "Found a new tag[title={0}] in article[title={1}]",
tagTitle, article.optString(Article.ARTICLE_TITLE));
tag.put(Tag.TAG_TITLE, tagTitle);
tag.put(Tag.TAG_REFERENCE_COUNT, 1);
tag.put(Tag.TAG_PUBLISHED_REFERENCE_COUNT, 1);
final String tagId = tagRepository.add(tag);
tag.put(Keys.OBJECT_ID, tagId);
ret.put(tag);
}
return ret;
}
/**
* Initializes administrator with the specified request json object, and then logins it.
*
* @param requestJSONObject the specified request json object, for example, <pre>
* {
* "userName": "",
* "userEmail": "",
* "userPassowrd": "" // Unhashed
* }
* </pre>
*
* @throws Exception exception
*/
private void initAdmin(final JSONObject requestJSONObject) throws Exception {
LOGGER.debug("Initializing admin....");
final JSONObject admin = new JSONObject();
admin.put(User.USER_NAME, requestJSONObject.getString(User.USER_NAME));
admin.put(User.USER_EMAIL, requestJSONObject.getString(User.USER_EMAIL));
admin.put(User.USER_URL, Latkes.getServePath());
admin.put(User.USER_ROLE, Role.ADMIN_ROLE);
admin.put(User.USER_PASSWORD, MD5.hash(requestJSONObject.getString(User.USER_PASSWORD)));
admin.put(UserExt.USER_ARTICLE_COUNT, 0);
admin.put(UserExt.USER_PUBLISHED_ARTICLE_COUNT, 0);
admin.put(UserExt.USER_AVATAR, Thumbnails.getGravatarURL(requestJSONObject.getString(User.USER_EMAIL), "128"));
userRepository.add(admin);
LOGGER.debug("Initialized admin");
}
/**
* Initializes link.
*
* @throws Exception exception
*/
private void initLink() throws Exception {
final JSONObject link = new JSONObject();
link.put(Link.LINK_TITLE, "黑客派");
link.put(Link.LINK_ADDRESS, "https://hacpai.com");
link.put(Link.LINK_DESCRIPTION, "黑客与画家的社区");
final int maxOrder = linkRepository.getMaxOrder();
link.put(Link.LINK_ORDER, maxOrder + 1);
final String ret = linkRepository.add(link);
}
/**
* Initializes statistic.
*
* @throws RepositoryException repository exception
* @throws JSONException json exception
*/
private void initStatistic() throws RepositoryException, JSONException {
LOGGER.debug("Initializing statistic....");
final JSONObject statistic = new JSONObject();
statistic.put(Keys.OBJECT_ID, Statistic.STATISTIC);
statistic.put(Statistic.STATISTIC_BLOG_ARTICLE_COUNT, 0);
statistic.put(Statistic.STATISTIC_PUBLISHED_ARTICLE_COUNT, 0);
statistic.put(Statistic.STATISTIC_BLOG_VIEW_COUNT, 0);
statistic.put(Statistic.STATISTIC_BLOG_COMMENT_COUNT, 0);
statistic.put(Statistic.STATISTIC_PUBLISHED_BLOG_COMMENT_COUNT, 0);
statisticRepository.add(statistic);
LOGGER.debug("Initialized statistic");
}
/**
* Initializes reply notification template.
*
* @throws Exception exception
*/
private void initReplyNotificationTemplate() throws Exception {
LOGGER.debug("Initializing reply notification template");
final JSONObject replyNotificationTemplate = new JSONObject(DefaultPreference.DEFAULT_REPLY_NOTIFICATION_TEMPLATE);
replyNotificationTemplate.put(Keys.OBJECT_ID, "replyNotificationTemplate");
final JSONObject subjectOpt = new JSONObject();
subjectOpt.put(Keys.OBJECT_ID, Option.ID_C_REPLY_NOTI_TPL_SUBJECT);
subjectOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
subjectOpt.put(Option.OPTION_VALUE, replyNotificationTemplate.optString("subject"));
optionRepository.add(subjectOpt);
final JSONObject bodyOpt = new JSONObject();
bodyOpt.put(Keys.OBJECT_ID, Option.ID_C_REPLY_NOTI_TPL_BODY);
bodyOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
bodyOpt.put(Option.OPTION_VALUE, replyNotificationTemplate.optString("body"));
optionRepository.add(bodyOpt);
LOGGER.debug("Initialized reply notification template");
}
/**
* Initializes preference.
*
* @param requestJSONObject the specified json object
* @throws Exception exception
*/
private void initPreference(final JSONObject requestJSONObject) throws Exception {
LOGGER.debug("Initializing preference....");
final JSONObject noticeBoardOpt = new JSONObject();
noticeBoardOpt.put(Keys.OBJECT_ID, Option.ID_C_NOTICE_BOARD);
noticeBoardOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
noticeBoardOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_NOTICE_BOARD);
optionRepository.add(noticeBoardOpt);
final JSONObject metaDescriptionOpt = new JSONObject();
metaDescriptionOpt.put(Keys.OBJECT_ID, Option.ID_C_META_DESCRIPTION);
metaDescriptionOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
metaDescriptionOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_META_DESCRIPTION);
optionRepository.add(metaDescriptionOpt);
final JSONObject metaKeywordsOpt = new JSONObject();
metaKeywordsOpt.put(Keys.OBJECT_ID, Option.ID_C_META_KEYWORDS);
metaKeywordsOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
metaKeywordsOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_META_KEYWORDS);
optionRepository.add(metaKeywordsOpt);
final JSONObject htmlHeadOpt = new JSONObject();
htmlHeadOpt.put(Keys.OBJECT_ID, Option.ID_C_HTML_HEAD);
htmlHeadOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
htmlHeadOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_HTML_HEAD);
optionRepository.add(htmlHeadOpt);
final JSONObject relevantArticlesDisplayCountOpt = new JSONObject();
relevantArticlesDisplayCountOpt.put(Keys.OBJECT_ID, Option.ID_C_RELEVANT_ARTICLES_DISPLAY_CNT);
relevantArticlesDisplayCountOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
relevantArticlesDisplayCountOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_RELEVANT_ARTICLES_DISPLAY_COUNT);
optionRepository.add(relevantArticlesDisplayCountOpt);
final JSONObject randomArticlesDisplayCountOpt = new JSONObject();
randomArticlesDisplayCountOpt.put(Keys.OBJECT_ID, Option.ID_C_RANDOM_ARTICLES_DISPLAY_CNT);
randomArticlesDisplayCountOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
randomArticlesDisplayCountOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_RANDOM_ARTICLES_DISPLAY_COUNT);
optionRepository.add(randomArticlesDisplayCountOpt);
final JSONObject externalRelevantArticlesDisplayCountOpt = new JSONObject();
externalRelevantArticlesDisplayCountOpt.put(Keys.OBJECT_ID, Option.ID_C_EXTERNAL_RELEVANT_ARTICLES_DISPLAY_CNT);
externalRelevantArticlesDisplayCountOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
externalRelevantArticlesDisplayCountOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_EXTERNAL_RELEVANT_ARTICLES_DISPLAY_COUNT);
optionRepository.add(externalRelevantArticlesDisplayCountOpt);
final JSONObject mostViewArticleDisplayCountOpt = new JSONObject();
mostViewArticleDisplayCountOpt.put(Keys.OBJECT_ID, Option.ID_C_MOST_VIEW_ARTICLE_DISPLAY_CNT);
mostViewArticleDisplayCountOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
mostViewArticleDisplayCountOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_MOST_VIEW_ARTICLES_DISPLAY_COUNT);
optionRepository.add(mostViewArticleDisplayCountOpt);
final JSONObject articleListDisplayCountOpt = new JSONObject();
articleListDisplayCountOpt.put(Keys.OBJECT_ID, Option.ID_C_ARTICLE_LIST_DISPLAY_COUNT);
articleListDisplayCountOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
articleListDisplayCountOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_ARTICLE_LIST_DISPLAY_COUNT);
optionRepository.add(articleListDisplayCountOpt);
final JSONObject articleListPaginationWindowSizeOpt = new JSONObject();
articleListPaginationWindowSizeOpt.put(Keys.OBJECT_ID, Option.ID_C_ARTICLE_LIST_PAGINATION_WINDOW_SIZE);
articleListPaginationWindowSizeOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
articleListPaginationWindowSizeOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_ARTICLE_LIST_PAGINATION_WINDOW_SIZE);
optionRepository.add(articleListPaginationWindowSizeOpt);
final JSONObject mostUsedTagDisplayCountOpt = new JSONObject();
mostUsedTagDisplayCountOpt.put(Keys.OBJECT_ID, Option.ID_C_MOST_USED_TAG_DISPLAY_CNT);
mostUsedTagDisplayCountOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
mostUsedTagDisplayCountOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_MOST_USED_TAG_DISPLAY_COUNT);
optionRepository.add(mostUsedTagDisplayCountOpt);
final JSONObject mostCommentArticleDisplayCountOpt = new JSONObject();
mostCommentArticleDisplayCountOpt.put(Keys.OBJECT_ID, Option.ID_C_MOST_COMMENT_ARTICLE_DISPLAY_CNT);
mostCommentArticleDisplayCountOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
mostCommentArticleDisplayCountOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_MOST_COMMENT_ARTICLE_DISPLAY_COUNT);
optionRepository.add(mostCommentArticleDisplayCountOpt);
final JSONObject recentArticleDisplayCountOpt = new JSONObject();
recentArticleDisplayCountOpt.put(Keys.OBJECT_ID, Option.ID_C_RECENT_ARTICLE_DISPLAY_CNT);
recentArticleDisplayCountOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
recentArticleDisplayCountOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_RECENT_ARTICLE_DISPLAY_COUNT);
optionRepository.add(recentArticleDisplayCountOpt);
final JSONObject recentCommentDisplayCountOpt = new JSONObject();
recentCommentDisplayCountOpt.put(Keys.OBJECT_ID, Option.ID_C_RECENT_COMMENT_DISPLAY_CNT);
recentCommentDisplayCountOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
recentCommentDisplayCountOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_RECENT_COMMENT_DISPLAY_COUNT);
optionRepository.add(recentCommentDisplayCountOpt);
final JSONObject blogTitleOpt = new JSONObject();
blogTitleOpt.put(Keys.OBJECT_ID, Option.ID_C_BLOG_TITLE);
blogTitleOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
blogTitleOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_BLOG_TITLE);
optionRepository.add(blogTitleOpt);
final JSONObject blogSubtitleOpt = new JSONObject();
blogSubtitleOpt.put(Keys.OBJECT_ID, Option.ID_C_BLOG_SUBTITLE);
blogSubtitleOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
blogSubtitleOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_BLOG_SUBTITLE);
optionRepository.add(blogSubtitleOpt);
final JSONObject adminEmailOpt = new JSONObject();
adminEmailOpt.put(Keys.OBJECT_ID, Option.ID_C_ADMIN_EMAIL);
adminEmailOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
adminEmailOpt.put(Option.OPTION_VALUE, requestJSONObject.getString(User.USER_EMAIL));
optionRepository.add(adminEmailOpt);
final JSONObject localeStringOpt = new JSONObject();
localeStringOpt.put(Keys.OBJECT_ID, Option.ID_C_LOCALE_STRING);
localeStringOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
localeStringOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_LANGUAGE);
optionRepository.add(localeStringOpt);
final JSONObject enableArticleUpdateHintOpt = new JSONObject();
enableArticleUpdateHintOpt.put(Keys.OBJECT_ID, Option.ID_C_ENABLE_ARTICLE_UPDATE_HINT);
enableArticleUpdateHintOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
enableArticleUpdateHintOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_ENABLE_ARTICLE_UPDATE_HINT);
optionRepository.add(enableArticleUpdateHintOpt);
final JSONObject signsOpt = new JSONObject();
signsOpt.put(Keys.OBJECT_ID, Option.ID_C_SIGNS);
signsOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
signsOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_SIGNS);
optionRepository.add(signsOpt);
final JSONObject timeZoneIdOpt = new JSONObject();
timeZoneIdOpt.put(Keys.OBJECT_ID, Option.ID_C_TIME_ZONE_ID);
timeZoneIdOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
timeZoneIdOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_TIME_ZONE);
optionRepository.add(timeZoneIdOpt);
final JSONObject allowVisitDraftViaPermalinkOpt = new JSONObject();
allowVisitDraftViaPermalinkOpt.put(Keys.OBJECT_ID, Option.ID_C_ALLOW_VISIT_DRAFT_VIA_PERMALINK);
allowVisitDraftViaPermalinkOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
allowVisitDraftViaPermalinkOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_ALLOW_VISIT_DRAFT_VIA_PERMALINK);
optionRepository.add(allowVisitDraftViaPermalinkOpt);
final JSONObject allowRegisterOpt = new JSONObject();
allowRegisterOpt.put(Keys.OBJECT_ID, Option.ID_C_ALLOW_REGISTER);
allowRegisterOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
allowRegisterOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_ALLOW_REGISTER);
optionRepository.add(allowRegisterOpt);
final JSONObject commentableOpt = new JSONObject();
commentableOpt.put(Keys.OBJECT_ID, Option.ID_C_COMMENTABLE);
commentableOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
commentableOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_COMMENTABLE);
optionRepository.add(commentableOpt);
final JSONObject versionOpt = new JSONObject();
versionOpt.put(Keys.OBJECT_ID, Option.ID_C_VERSION);
versionOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
versionOpt.put(Option.OPTION_VALUE, SoloServletListener.VERSION);
optionRepository.add(versionOpt);
final JSONObject articleListStyleOpt = new JSONObject();
articleListStyleOpt.put(Keys.OBJECT_ID, Option.ID_C_ARTICLE_LIST_STYLE);
articleListStyleOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
articleListStyleOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_ARTICLE_LIST_STYLE);
optionRepository.add(articleListStyleOpt);
final JSONObject keyOfSoloOpt = new JSONObject();
keyOfSoloOpt.put(Keys.OBJECT_ID, Option.ID_C_KEY_OF_SOLO);
keyOfSoloOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
keyOfSoloOpt.put(Option.OPTION_VALUE, Ids.genTimeMillisId());
optionRepository.add(keyOfSoloOpt);
final JSONObject feedOutputModeOpt = new JSONObject();
feedOutputModeOpt.put(Keys.OBJECT_ID, Option.ID_C_FEED_OUTPUT_MODE);
feedOutputModeOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
feedOutputModeOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_FEED_OUTPUT_MODE);
optionRepository.add(feedOutputModeOpt);
final JSONObject feedOutputCntOpt = new JSONObject();
feedOutputCntOpt.put(Keys.OBJECT_ID, Option.ID_C_FEED_OUTPUT_CNT);
feedOutputCntOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
feedOutputCntOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_FEED_OUTPUT_CNT);
optionRepository.add(feedOutputCntOpt);
final JSONObject editorTypeOpt = new JSONObject();
editorTypeOpt.put(Keys.OBJECT_ID, Option.ID_C_EDITOR_TYPE);
editorTypeOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
editorTypeOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_EDITOR_TYPE);
optionRepository.add(editorTypeOpt);
final JSONObject footerContentOpt = new JSONObject();
footerContentOpt.put(Keys.OBJECT_ID, Option.ID_C_FOOTER_CONTENT);
footerContentOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
footerContentOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_FOOTER_CONTENT);
optionRepository.add(footerContentOpt);
final String skinDirName = DefaultPreference.DEFAULT_SKIN_DIR_NAME;
final JSONObject skinDirNameOpt = new JSONObject();
skinDirNameOpt.put(Keys.OBJECT_ID, Option.ID_C_SKIN_DIR_NAME);
skinDirNameOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
skinDirNameOpt.put(Option.OPTION_VALUE, skinDirName);
optionRepository.add(skinDirNameOpt);
final String skinName = Latkes.getSkinName(skinDirName);
final JSONObject skinNameOpt = new JSONObject();
skinNameOpt.put(Keys.OBJECT_ID, Option.ID_C_SKIN_NAME);
skinNameOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
skinNameOpt.put(Option.OPTION_VALUE, skinName);
optionRepository.add(skinNameOpt);
final Set<String> skinDirNames = Skins.getSkinDirNames();
final JSONArray skinArray = new JSONArray();
for (final String dirName : skinDirNames) {
final JSONObject skin = new JSONObject();
skinArray.put(skin);
final String name = Latkes.getSkinName(dirName);
skin.put(Skin.SKIN_NAME, name);
skin.put(Skin.SKIN_DIR_NAME, dirName);
}
final JSONObject skinsOpt = new JSONObject();
skinsOpt.put(Keys.OBJECT_ID, Option.ID_C_SKINS);
skinsOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
skinsOpt.put(Option.OPTION_VALUE, skinArray.toString());
optionRepository.add(skinsOpt);
final ServletContext servletContext = SoloServletListener.getServletContext();
Templates.MAIN_CFG.setServletContextForTemplateLoading(servletContext, "/skins/" + skinDirName);
TimeZones.setTimeZone(INIT_TIME_ZONE_ID);
LOGGER.debug("Initialized preference");
}
/**
* Sets archive date article repository with the specified archive date article repository.
*
* @param archiveDateArticleRepository the specified archive date article repository
*/
public void setArchiveDateArticleRepository(final ArchiveDateArticleRepository archiveDateArticleRepository) {
this.archiveDateArticleRepository = archiveDateArticleRepository;
}
/**
* Sets archive date repository with the specified archive date repository.
*
* @param archiveDateRepository the specified archive date repository
*/
public void setArchiveDateRepository(final ArchiveDateRepository archiveDateRepository) {
this.archiveDateRepository = archiveDateRepository;
}
/**
* Sets the article repository with the specified article repository.
*
* @param articleRepository the specified article repository
*/
public void setArticleRepository(final ArticleRepository articleRepository) {
this.articleRepository = articleRepository;
}
/**
* Sets the user repository with the specified user repository.
*
* @param userRepository the specified user repository
*/
public void setUserRepository(final UserRepository userRepository) {
this.userRepository = userRepository;
}
/**
* Sets the statistic repository with the specified statistic repository.
*
* @param statisticRepository the specified statistic repository
*/
public void setStatisticRepository(final StatisticRepository statisticRepository) {
this.statisticRepository = statisticRepository;
}
/**
* Sets the tag repository with the specified tag repository.
*
* @param tagRepository the specified tag repository
*/
public void setTagRepository(final TagRepository tagRepository) {
this.tagRepository = tagRepository;
}
/**
* Sets the tag article repository with the specified tag article repository.
*
* @param tagArticleRepository the specified tag article repository
*/
public void setTagArticleRepository(final TagArticleRepository tagArticleRepository) {
this.tagArticleRepository = tagArticleRepository;
}
/**
* Sets the comment repository with the specified comment repository.
*
* @param commentRepository the specified comment repository
*/
public void setCommentRepository(final CommentRepository commentRepository) {
this.commentRepository = commentRepository;
}
/**
* Sets the language service with the specified language service.
*
* @param langPropsService the specified language service
*/
public void setLangPropsService(final LangPropsService langPropsService) {
this.langPropsService = langPropsService;
}
/**
* Sets the plugin manager with the specified plugin manager.
*
* @param pluginManager the specified plugin manager
*/
public void setPluginManager(final PluginManager pluginManager) {
this.pluginManager = pluginManager;
}
}