diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7278377
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.settings
+.vscode
+target
+.classpath
+.project
diff --git a/README.md b/README.md
index b54cc18..29d1ba7 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,340 @@
-# confluence-rest-extender
+[](https://www.tiburon.su)
+REST API Extender for Confluence
+================
+
+REST API for automated Confluence configuration with URMS
+
+
+Resources
+---------
+
+All resources produce JSON (media type: `application/json`) results.
+
+### Page versions
+
+Get and delete outdated page versions
+
+* #### `GET /rest/extender/1/api/versions/all`
+
+ **QueryString**
+ - type: all or page or attachment. (default:all)
+ - endDays: 1~ (0=today, 1=yesterday) (default:0)
+ - limit: 1~1000 (default:1000)
+
+ Get all page versions in all instance.
+
+ __Responses__
+
+ ![Status 200][status-200]
+
+ ![Status 401][status-401]
+
+ Returned if the current user is not authenticated.
+
+ ![Status 403][status-403]
+
+ Returned if the current user is not an administrator.
+
+* #### `DELETE /rest/extender/1/api/versions/all`
+
+ **QueryString**
+ - type: all or page or attachment. (default:all)
+ - endDays: 1~ (0=today, 1=yesterday) (default:0)
+ - limit: 1~1000 (default:1000)
+
+ Remove all page versions in all instance.
+
+ __Responses__
+
+ ![Status 200][status-200]
+
+ ![Status 401][status-401]
+
+ Returned if the current user is not authenticated.
+
+ ![Status 403][status-403]
+
+ Returned if the current user is not an administrator.
+
+
+* #### `GET /rest/extender/1/api/versions/space/{spaceKey}`
+
+ **QueryString**
+ - spaceKey: Key of the target space. (required)
+ - type: all or page or attachment. (default:all)
+ - endDays: 1~ (0=today, 1=yesterday) (default:0)
+ - limit: 1~1000 (default:1000)
+
+ Get all page versions in space with key=`spaceKey`.
+
+ __Responses__
+
+ ![Status 200][status-200]
+
+ ![Status 401][status-401]
+
+ Returned if the current user is not authenticated.
+
+ ![Status 403][status-403]
+
+ Returned if the current user is not an administrator.
+
+* #### `DELETE /rest/extender/1/api/versions/space/{spaceKey}`
+
+ **QueryString**
+ - spaceKey: Key of the target space. (required)
+ - type: all or page or attachment. (default:all)
+ - endDays: 1~ (0=today, 1=yesterday) (default:0)
+ - limit: 1~1000 (default:1000)
+
+ Remove all page versions in space with key=`spaceKey`.
+
+ __Responses__
+
+ ![Status 200][status-200]
+
+ ![Status 401][status-401]
+
+ Returned if the current user is not authenticated.
+
+ ![Status 403][status-403]
+
+ Returned if the current user is not an administrator.
+
+
+* #### `GET /rest/extender/1/api/versions/page/{pageId}`
+
+ **QueryString**
+ - pageId: Id of the target page. (required)
+ - type: all or page or attachment. (default:all)
+ - endDays: 1~ (0=today, 1=yesterday) (default:0)
+ - limit: 1~1000 (default:1000)
+
+ Get versions of the page with id=`pageId`.
+
+ __Responses__
+
+ ![Status 200][status-200]
+
+ ![Status 401][status-401]
+
+ Returned if the current user is not authenticated.
+
+ ![Status 403][status-403]
+
+ Returned if the current user is not an administrator.
+
+* #### `DELETE /rest/extender/1/api/versions/page/{pageId}`
+
+ **QueryString**
+ - pageId: Id of the target page. (required)
+ - type: all or page or attachment. (default:all)
+ - endDays: 1~ (0=today, 1=yesterday) (default:0)
+ - limit: 1~1000 (default:1000)
+
+ Remove versions of the page with id=`pageId`.
+
+ __Responses__
+
+ ![Status 200][status-200]
+
+ ![Status 401][status-401]
+
+ Returned if the current user is not authenticated.
+
+ ![Status 403][status-403]
+
+ Returned if the current user is not an administrator.
+
+### Trashes
+
+Get and delete trash
+
+* #### `GET /rest/extender/1/api/trash/all`
+
+ **QueryString**
+ - limit: 1~1000 (default:1000)
+
+ Get all trash in all instance.
+
+ __Responses__
+
+ ![Status 200][status-200]
+
+ ![Status 401][status-401]
+
+ Returned if the current user is not authenticated.
+
+ ![Status 403][status-403]
+
+ Returned if the current user is not an administrator.
+
+* #### `DELETE /rest/extender/1/api/trash/all`
+
+ **QueryString**
+ - limit: 1~1000 (default:1000)
+
+ Remove all trash in all instance.
+
+ __Responses__
+
+ ![Status 200][status-200]
+
+ ![Status 401][status-401]
+
+ Returned if the current user is not authenticated.
+
+ ![Status 403][status-403]
+
+ Returned if the current user is not an administrator.
+
+
+* #### `GET /rest/extender/1/api/trash/space/{spaceKey}`
+
+ **QueryString**
+ - spaceKey: Key of the target space. (required)
+ - limit: 1~1000 (default:1000)
+
+ Get trash from space with key=`spaceKey`.
+
+ __Responses__
+
+ ![Status 200][status-200]
+
+ ![Status 401][status-401]
+
+ Returned if the current user is not authenticated.
+
+ ![Status 403][status-403]
+
+ Returned if the current user is not an administrator.
+
+* #### `DELETE /rest/extender/1/api/trash/space/{spaceKey}`
+
+ **QueryString**
+ - spaceKey: Key of the target space. (required)
+ - limit: 1~1000 (default:1000)
+
+ Remove trash from space with key=`spaceKey`.
+
+ __Responses__
+
+ ![Status 200][status-200]
+
+ ![Status 401][status-401]
+
+ Returned if the current user is not authenticated.
+
+ ![Status 403][status-403]
+
+ Returned if the current user is not an administrator.
+
+
+
+
+ **QueryString**
+ - type: all or page or attachment. (default:all)
+ - endDays: 1~ (0=today, 1=yesterday) (default:0)
+ - limit: 1~1000 (default:1000)
+
+ Remove versions of the page with id=`pageId`.
+
+ __Responses__
+
+ ![Status 200][status-200]
+
+ ![Status 401][status-401]
+
+ Returned if the current user is not authenticated.
+
+ ![Status 403][status-403]
+
+ Returned if the current user is not an administrator.
+
+
+
+
+
+
+
+
+
+
+
+### Syncronise Crowd User Directory
+
+* #### `GET /rest/extender/1/directory`
+
+ Get info about User Directories.
+
+ __Responses__
+
+ ![Status 200][status-200]
+
+ ```javascript
+ [
+ {
+ "id": 262145,
+ "type": "INTERNAL",
+ "issynchronising": false
+ },
+ {
+ "id": 1277953,
+ "type": "CROWD",
+ "issynchronising": false
+ }
+ ]
+ ```
+
+ ![Status 401][status-401]
+
+ Returned if the current user is not authenticated.
+
+ ![Status 403][status-403]
+
+ Returned if the current user is not an administrator.
+
+* #### `PUT /rest/extender/1/directory`
+
+
+ **QueryString**
+ - id: User Directory ID. (required)
+
+ Start sycronyse User Directory.
+
+ __Responses__
+
+ ![Status 200][status-200]
+
+ If OK, `issynchronising` of target directory returned as `true`
+
+ ```javascript
+ [
+ {
+ "id": 262145,
+ "type": "INTERNAL",
+ "issynchronising": false
+ },
+ {
+ "id": 1277953,
+ "type": "CROWD",
+ "issynchronising": true
+ }
+ ]
+ ```
+
+ ![Status 401][status-401]
+
+ Returned if the current user is not authenticated.
+
+ ![Status 403][status-403]
+
+ Returned if the current user is not an administrator.
+
+
+[status-200]: https://img.shields.io/badge/status-200-brightgreen.svg
+[status-400]: https://img.shields.io/badge/status-400-red.svg
+[status-401]: https://img.shields.io/badge/status-401-red.svg
+[status-403]: https://img.shields.io/badge/status-403-red.svg
+[status-404]: https://img.shields.io/badge/status-404-red.svg
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..0d6ed8c
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,229 @@
+
+
+
+
+ 4.0.0
+
+ su.tiburon.confluence
+ rest-extender
+ 1.1.1
+ atlassian-plugin
+
+ REST API extender for Confluence
+ REST API extender for Confluence.
+
+
+
+ BSD 3-Clause License
+ https://opensource.org/licenses/BSD-3-Clause
+
+
+
+
+ Github
+ https://github.com/tiburon-777/confluence-rest-extender/issues
+
+
+
+ scm:git:git://github.com/tiburon-777/confluence-rest-extender.git
+ scm:git:git@github.com:tiburon-777/confluence-rest-extender.git
+ https://github.com/tiburon-777/confluence-rest-extender
+
+
+
+ OCTOPUS CodeWare
+ http://www.tiburon.su/
+
+
+
+
+ Andrey Ivanov
+ ya@tiburon.su
+ OCTOPUS CodeWare
+ https://www.tiburon.su
+
+
+
+
+
+ atlassian-public
+ https://packages.atlassian.com/maven/repository/public
+
+ true
+ never
+ warn
+
+
+ true
+ warn
+
+
+
+
+
+ atlassian-public
+ https://m2proxy.atlassian.com/repository/public/
+
+ true
+
+
+ true
+
+
+
+
+
+ org.json
+ json
+ 20090211
+
+
+ junit
+ junit
+ 4.10
+ test
+
+
+ com.atlassian.confluence
+ confluence
+ ${confluence.version}
+ provided
+
+
+ com.atlassian.plugin
+ atlassian-spring-scanner-annotation
+ ${atlassian.spring.scanner.version}
+ provided
+
+
+ javax.inject
+ javax.inject
+ 1
+ provided
+
+
+
+ com.atlassian.plugins
+ atlassian-plugins-osgi-testrunner
+ ${plugin.testrunner.version}
+ test
+
+
+ javax.ws.rs
+ jsr311-api
+ 1.1.1
+ provided
+
+
+ com.google.code.gson
+ gson
+ 2.2.2-atlassian-1
+
+
+ javax.servlet
+ servlet-api
+ 2.4
+ provided
+
+
+ javax.xml.bind
+ jaxb-api
+ 2.3.1
+ provided
+
+
+ com.atlassian.plugins.rest
+ atlassian-rest-common
+ 1.0.2
+ provided
+
+
+ com.atlassian.sal
+ sal-api
+ 2.10.10
+ provided
+
+
+ org.apache.wink
+ wink-client
+ 1.4
+ test
+
+
+ org.mockito
+ mockito-all
+ 1.8.5
+ test
+
+
+
+
+
+ com.atlassian.maven.plugins
+ confluence-maven-plugin
+ ${amps.version}
+ true
+
+ ${confluence.version}
+ ${confluence.data.version}
+ true
+
+
+
+ ${atlassian.plugin.key}
+
+ sample.api
+
+
+
+
+
+ com.atlassian.confluence.*;resolution:="optional",
+
+ *
+
+
+ *
+
+ true
+
+
+
+ com.atlassian.plugin
+ atlassian-spring-scanner-maven-plugin
+ ${atlassian.spring.scanner.version}
+
+
+
+ atlassian-spring-scanner
+
+ process-classes
+
+
+
+
+
+ com.atlassian.plugin
+ atlassian-spring-scanner-external-jar
+
+
+ false
+
+
+
+
+
+ 6.14.0
+ 6.14.0
+ 8.0.0
+ 2.0.1
+ 2.1.8
+
+ ${project.groupId}.${project.artifactId}
+ UTF-8
+ 1.8
+ 1.8
+
+
diff --git a/src/main/java/su/tiburon/atlassian/confluence/api/DataCleanUtil.java b/src/main/java/su/tiburon/atlassian/confluence/api/DataCleanUtil.java
new file mode 100644
index 0000000..d2d206f
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/api/DataCleanUtil.java
@@ -0,0 +1,49 @@
+package su.tiburon.atlassian.confluence.api;
+
+import java.util.Date;
+import java.util.List;
+
+import com.atlassian.confluence.pages.AbstractPage;
+import com.atlassian.confluence.pages.Attachment;
+import com.atlassian.confluence.pages.Page;
+import com.atlassian.confluence.spaces.Space;
+
+import su.tiburon.atlassian.confluence.rest.PageVersionsModel;
+import su.tiburon.atlassian.confluence.rest.SpaceTrashModel;
+import su.tiburon.atlassian.confluence.rest.SpaceVersionsModel;
+
+public interface DataCleanUtil {
+ public abstract Date getCreatedOrUpdatedDate(int paramInt);
+
+ public abstract List getAttachmentVersions(Attachment attachment, int endDays);
+
+ public abstract List getPageVersions(Page page, int endDays, String type);
+
+ public abstract long removePageVersions(Page paramPage, int paramInt, String paramString);
+
+ public abstract long removeSpaceVersions(Space paramSpace, int paramInt, String paramString);
+
+ public abstract long removeAllVersions(int paramInt, String paramString);
+
+ public abstract int removeSpaceTrash(Space paramSpace);
+
+ public abstract long removeAllTrash();
+
+ public abstract PageVersionsModel getPageVersionSummary(Page page, int endDays, String type);
+
+ public abstract SpaceVersionsModel getSpaceVersionSummary(Space paramSpace, int paramInt, String paramString);
+
+ public abstract List getAllVersionSummary(int paramInt, String paramString);
+
+ public abstract SpaceTrashModel getSpaceTrashSummary(Space paramSpace);
+
+ public abstract List getAllTrashSummary();
+
+ public abstract void setLimit(int paramInt);
+
+ public abstract int getLimit();
+
+ public abstract void setCount(int paramInt);
+
+ public abstract int getCount();
+}
diff --git a/src/main/java/su/tiburon/atlassian/confluence/api/DateTimeUtil.java b/src/main/java/su/tiburon/atlassian/confluence/api/DateTimeUtil.java
new file mode 100644
index 0000000..d6f5fdf
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/api/DateTimeUtil.java
@@ -0,0 +1,7 @@
+package su.tiburon.atlassian.confluence.api;
+
+import java.util.Date;
+
+public interface DateTimeUtil {
+ public abstract Date getDate();
+}
diff --git a/src/main/java/su/tiburon/atlassian/confluence/impl/DataCleanUtilImpl.java b/src/main/java/su/tiburon/atlassian/confluence/impl/DataCleanUtilImpl.java
new file mode 100644
index 0000000..bb3c330
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/impl/DataCleanUtilImpl.java
@@ -0,0 +1,364 @@
+package su.tiburon.atlassian.confluence.impl;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.atlassian.confluence.core.VersionHistorySummary;
+import com.atlassian.confluence.pages.AbstractPage;
+import com.atlassian.confluence.pages.Attachment;
+import com.atlassian.confluence.pages.AttachmentManager;
+import com.atlassian.confluence.pages.Page;
+import com.atlassian.confluence.pages.PageManager;
+import com.atlassian.confluence.pages.TrashManager;
+import com.atlassian.confluence.spaces.Space;
+import com.atlassian.confluence.spaces.SpaceManager;
+import com.atlassian.plugin.spring.scanner.annotation.export.ExportAsService;
+import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
+
+import su.tiburon.atlassian.confluence.api.DataCleanUtil;
+import su.tiburon.atlassian.confluence.api.DateTimeUtil;
+import su.tiburon.atlassian.confluence.rest.AttachmentModel;
+import su.tiburon.atlassian.confluence.rest.PageVersionsModel;
+import su.tiburon.atlassian.confluence.rest.SpaceTrashModel;
+import su.tiburon.atlassian.confluence.rest.SpaceVersionsModel;
+
+@ExportAsService
+@Named
+public class DataCleanUtilImpl implements DataCleanUtil {
+ private static final Logger logger = LoggerFactory.getLogger(DataCleanUtil.class);
+
+ @ComponentImport
+ private final PageManager pageManager;
+ @ComponentImport
+ private final AttachmentManager attachmentManager;
+ @ComponentImport
+ private final TrashManager trashManager;
+ @ComponentImport
+ private final SpaceManager spaceManager;
+ private DateTimeUtil dateTimeUtil;
+ private int limit;
+ private int count;
+
+ @Inject
+ public DataCleanUtilImpl(PageManager pageManager, AttachmentManager attachmentManager, TrashManager trashManager, SpaceManager spaceManager, DateTimeUtil dateTimeUtil) {
+ this.pageManager = pageManager;
+ this.attachmentManager = attachmentManager;
+ this.trashManager = trashManager;
+ this.spaceManager = spaceManager;
+ this.limit = 1000;
+ this.count = 0;
+ this.dateTimeUtil = dateTimeUtil;
+ }
+
+ @Override
+ public Date getCreatedOrUpdatedDate(int endDays) {
+ Date defaultDate = dateTimeUtil.getDate();
+ try {
+ int lastCreatedOrUpdated = Integer.parseInt("-" + endDays);
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(defaultDate);
+ cal.add(Calendar.DAY_OF_MONTH, lastCreatedOrUpdated);
+ return cal.getTime();
+
+ } catch (NumberFormatException e) {
+ logger.error(e.getMessage(), e);
+
+ }
+
+ return defaultDate;
+ }
+
+ @Override
+ public List getAttachmentVersions(Attachment attachment, int endDays) {
+ List resultAttachments = new ArrayList();
+ Date lastUpdatedOrCreatedDate = getCreatedOrUpdatedDate(endDays);
+ List vAttachments = this.attachmentManager.getPreviousVersions(attachment);
+
+ for (Attachment vAttachment : vAttachments) {
+ if (vAttachment.getLastModificationDate().before(lastUpdatedOrCreatedDate)) {
+ resultAttachments.add(vAttachment);
+ }
+ }
+
+ return resultAttachments;
+ }
+
+ @Override
+ public List getPageVersions(Page page, int endDays, String type) {
+ List resultVersions = new ArrayList();
+ Date lastUpdatedOrCreatedDate = getCreatedOrUpdatedDate(endDays);
+ List versions = this.pageManager.getVersionHistorySummaries(page);
+
+ for (VersionHistorySummary vSummary : versions) {
+ if (page.getId() != vSummary.getId() && vSummary.getLastModificationDate().before(lastUpdatedOrCreatedDate)) {
+ AbstractPage vPage = this.pageManager.getPage(vSummary.getId());
+ if (vPage == null) {
+ vPage = this.pageManager.getBlogPost(vSummary.getId());
+
+ }
+ if (vPage != null) {
+ resultVersions.add(vPage);
+ }
+ }
+ }
+
+ return resultVersions;
+ }
+
+ @Override
+ public long removePageVersions(Page page, int endDays, String type) {
+ long delete_index = 0;
+ if (this.count >= this.limit) {
+ return delete_index;
+ }
+
+ if ("all".equals(type) || "page".equals(type)) {
+ List aPages = getPageVersions(page, endDays, type);
+
+ for (AbstractPage aPage : aPages) {
+ this.pageManager.removeHistoricalVersion(aPage);
+ delete_index++;
+ }
+
+ if (delete_index > 0) {
+ this.count++;
+ if (this.count >= this.limit) {
+ return delete_index;
+ }
+ }
+ }
+
+ if ("all".equals(type) || "attachment".equals(type)) {
+ List attachments = attachmentManager.getLatestVersionsOfAttachments(page);
+
+ for (Attachment attachment : attachments) {
+ List targetAttachments = getAttachmentVersions(attachment, endDays);
+
+ for (Attachment targetAttachment : targetAttachments) {
+ this.attachmentManager.removeAttachmentVersionFromServer(targetAttachment);
+ delete_index++;
+ }
+
+ if (targetAttachments.size() > 0) {
+ this.count++;
+ if (this.count >= this.limit) {
+ return delete_index;
+ }
+ }
+ }
+ }
+
+ return delete_index;
+ }
+
+ @Override
+ public long removeSpaceVersions(Space space, int endDays, String type) {
+ Date lastUpdatedOrCreatedDate = getCreatedOrUpdatedDate(endDays);
+ Collection pages = this.pageManager.getPages(space, true);
+ long delete_index = 0L;
+
+ for (Page page : pages) {
+ if (page.getCreationDate().before(lastUpdatedOrCreatedDate)) {
+ delete_index += removePageVersions(page, endDays, type);
+
+ if (this.count >= this.limit) {
+ return delete_index;
+ }
+ }
+ }
+
+ return delete_index;
+ }
+
+ @Override
+ public long removeAllVersions(int endDays, String type) {
+ long delete_index = 0L;
+ for (Space space : this.spaceManager.getAllSpaces()) {
+ delete_index += this.removeSpaceVersions(space, endDays, type);
+
+ if (this.count >= this.limit) {
+ return delete_index;
+ }
+ }
+ return delete_index;
+ }
+
+ @Override
+ public int removeSpaceTrash(Space space) {
+ int numberOfItems = this.trashManager.getNumberOfItemsInTrash(space);
+ this.trashManager.emptyTrash(space);
+
+ return numberOfItems;
+ }
+
+ @Override
+ public long removeAllTrash() {
+ long deleted = 0L;
+ for (Space space : this.spaceManager.getAllSpaces()) {
+ deleted += this.removeSpaceTrash(space);
+
+ this.count++;
+ if (this.count >= this.limit) {
+ return deleted;
+ }
+ }
+ return deleted;
+ }
+
+ @Override
+ public PageVersionsModel getPageVersionSummary(Page page, int endDays, String type) {
+ List resultVersions = new ArrayList();
+ if ("all".equals(type) || "page".equals(type)) {
+ resultVersions = getPageVersions(page, endDays, type);
+ }
+ PageVersionsModel pageModel = new PageVersionsModel();
+ String modifier = page.getLastModifier() != null ? page.getLastModifier().getName() : "";
+ pageModel.setId(page.getId());
+ pageModel.setTitle(page.getTitle());
+ pageModel.setVersionCount(resultVersions.size());
+ pageModel.setLastModifier(modifier);
+ pageModel.setLastModified(page.getLastModificationDate());
+
+ long totalPageVersionCount = pageModel.getVersionCount();
+ if (pageModel.getVersionCount() > 0) {
+ this.count++;
+ if (this.count >= this.limit) {
+ pageModel.setTotalVersionCount(totalPageVersionCount);
+ return pageModel;
+
+ }
+ }
+
+ if ("all".equals(type) || "attachment".equals(type)) {
+ List attachments = attachmentManager.getLatestVersionsOfAttachments(page);
+ List attachmentVersions = new ArrayList();
+ List attachmentModels = new ArrayList();
+
+ for (Attachment attachment : attachments) {
+ List tmpAttachmentVersions = getAttachmentVersions(attachment, endDays);
+ int tmpAttachmentVersionsCount = tmpAttachmentVersions.size();
+
+ if (tmpAttachmentVersionsCount > 0) {
+ attachmentVersions.addAll(tmpAttachmentVersions);
+ totalPageVersionCount += tmpAttachmentVersions.size();
+ String last_modifier = attachment.getLastModifier() != null ? attachment.getLastModifier().getName() : "";
+ AttachmentModel model = new AttachmentModel(
+ attachment.getId(),
+ attachment.getTitle(),
+ tmpAttachmentVersionsCount,
+ last_modifier,
+ attachment.getLastModificationDate()
+ );
+ attachmentModels.add(model);
+ this.count++;
+ if (this.count >= this.limit) {
+ break;
+
+ }
+ }
+ }
+ pageModel.setAttachments(attachmentModels);
+
+ }
+
+ pageModel.setTotalVersionCount(totalPageVersionCount);
+ return pageModel;
+ }
+
+ @Override
+ public SpaceVersionsModel getSpaceVersionSummary(Space space, int endDays, String type) {
+ Collection pages = this.pageManager.getPages(space, true);
+ List pageModels = new ArrayList();
+
+ long totalSpaceVersionCount = 0;
+ for (Page page : pages) {
+ PageVersionsModel pageModel = getPageVersionSummary(page, endDays, type);
+
+ if (pageModel.getTotalVersionCount() > 0) {
+ totalSpaceVersionCount += pageModel.getTotalVersionCount();
+ pageModels.add(pageModel);
+ }
+
+ if (this.count >= this.limit) {
+ break;
+ }
+ }
+ SpaceVersionsModel spaceModel = new SpaceVersionsModel(space.getKey(), space.getDisplayTitle(), totalSpaceVersionCount, pageModels);
+
+ return spaceModel;
+ }
+
+ @Override
+ public List getAllVersionSummary(int endDays, String type) {
+ List spaceModels = new ArrayList();
+ for (Space space : this.spaceManager.getAllSpaces()) {
+ SpaceVersionsModel spaceModel = this.getSpaceVersionSummary(space, endDays, type);
+
+ if(spaceModel.getTotalVersionCount() > 0) {
+ spaceModels.add(spaceModel);
+ }
+
+ if (this.count >= this.limit) {
+ return spaceModels;
+ }
+ }
+ return spaceModels;
+ }
+
+ @Override
+ public SpaceTrashModel getSpaceTrashSummary(Space space) {
+ int numberOfItems = this.trashManager.getNumberOfItemsInTrash(space);
+ SpaceTrashModel trashModel = new SpaceTrashModel(space.getKey(), space.getDisplayTitle(), numberOfItems);
+
+ return trashModel;
+ }
+
+ @Override
+ public List getAllTrashSummary() {
+ List trashModels = new ArrayList();
+ for (Space space : this.spaceManager.getAllSpaces()) {
+ SpaceTrashModel trashModel = this.getSpaceTrashSummary(space);
+
+ if (trashModel.getNumberOfItemsInTrash() > 0) {
+
+ trashModels.add(trashModel);
+
+ this.count++;
+ if (this.count >= this.limit) {
+ return trashModels;
+ }
+ }
+ }
+ return trashModels;
+ }
+
+ @Override
+ public void setLimit(int limit) {
+ this.limit = limit;
+ }
+
+ @Override
+ public int getLimit() {
+ return this.limit;
+ }
+
+ @Override
+ public void setCount(int count) {
+ this.count = count;
+ }
+
+ @Override
+ public int getCount() {
+ return this.count;
+ }
+
+}
diff --git a/src/main/java/su/tiburon/atlassian/confluence/impl/DateTimeUtilImpl.java b/src/main/java/su/tiburon/atlassian/confluence/impl/DateTimeUtilImpl.java
new file mode 100644
index 0000000..8150975
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/impl/DateTimeUtilImpl.java
@@ -0,0 +1,21 @@
+package su.tiburon.atlassian.confluence.impl;
+
+import java.util.Date;
+
+import javax.inject.Named;
+
+import com.atlassian.plugin.spring.scanner.annotation.export.ExportAsService;
+
+import su.tiburon.atlassian.confluence.api.DateTimeUtil;
+
+@ExportAsService
+@Named
+public class DateTimeUtilImpl implements DateTimeUtil {
+
+ @Override
+ public Date getDate() {
+ return new Date();
+ }
+
+
+}
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/AllTrashModel.java b/src/main/java/su/tiburon/atlassian/confluence/rest/AllTrashModel.java
new file mode 100644
index 0000000..af8169e
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/AllTrashModel.java
@@ -0,0 +1,34 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class AllTrashModel {
+
+ @XmlElementWrapper
+ @XmlElement(name="trash")
+ public List trashList;
+
+ public AllTrashModel() {
+ this.trashList = new ArrayList();
+ }
+
+ public AllTrashModel(List trashList) {
+ this.trashList = trashList;
+ }
+
+ public List getTrashList() {
+ return trashList;
+ }
+
+ public void setTrashList(List trashList) {
+ this.trashList = trashList;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/AllVersionsModel.java b/src/main/java/su/tiburon/atlassian/confluence/rest/AllVersionsModel.java
new file mode 100644
index 0000000..42ae298
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/AllVersionsModel.java
@@ -0,0 +1,34 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class AllVersionsModel {
+
+ @XmlElementWrapper
+ @XmlElement(name="space")
+ public List spaces;
+
+ public AllVersionsModel() {
+ this.spaces = new ArrayList();
+ }
+
+ public AllVersionsModel(List spaces) {
+ this.spaces = spaces;
+ }
+
+ public List getSpaces() {
+ return spaces;
+ }
+
+ public void setSpaces(List spaces) {
+ this.spaces = spaces;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/AttachmentModel.java b/src/main/java/su/tiburon/atlassian/confluence/rest/AttachmentModel.java
new file mode 100644
index 0000000..87b262a
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/AttachmentModel.java
@@ -0,0 +1,79 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import java.util.Date;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class AttachmentModel {
+
+ @XmlElement
+ public String id;
+ @XmlElement
+ public String title;
+ @XmlElement
+ public int versionCount;
+ @XmlElement
+ public String lastModifier;
+ @XmlElement
+ public String lastModified;
+
+ public AttachmentModel() {
+ this.id = "";
+ this.title = "";
+ this.versionCount = -1;
+ this.lastModifier = "";
+ this.lastModified = "";
+ }
+
+ public AttachmentModel(Long id, String title, int versionCount, String lastModifier, Date lastModified) {
+ this.id = String.valueOf(id);
+ this.title = title;
+ this.versionCount = versionCount;
+ this.lastModifier = lastModifier;
+ this.lastModified = String.valueOf(lastModified);
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = String.valueOf(id);
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getVersionCount() {
+ return versionCount;
+ }
+
+ public void setVersionCount(int versionCount) {
+ this.versionCount = versionCount;
+ }
+
+ public String getLastModifier() {
+ return lastModifier;
+ }
+
+ public void setLastModifier(String lastModifier) {
+ this.lastModifier = lastModifier;
+ }
+
+ public String getLastModified() {
+ return lastModified;
+ }
+
+ public void setLastModified(Date lastModified) {
+ this.lastModified = String.valueOf(lastModified);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/Cleaner.java b/src/main/java/su/tiburon/atlassian/confluence/rest/Cleaner.java
new file mode 100644
index 0000000..a4e22fb
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/Cleaner.java
@@ -0,0 +1,456 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import java.text.MessageFormat;
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
+
+import com.atlassian.confluence.pages.Page;
+import com.atlassian.confluence.pages.PageManager;
+import com.atlassian.confluence.security.Permission;
+import com.atlassian.confluence.security.PermissionManager;
+import com.atlassian.confluence.spaces.Space;
+import com.atlassian.confluence.spaces.SpaceManager;
+import com.atlassian.confluence.user.AuthenticatedUserThreadLocal;
+import com.atlassian.confluence.user.ConfluenceUser;
+import com.atlassian.plugin.spring.scanner.annotation.imports.ConfluenceImport;
+import com.atlassian.plugins.rest.common.security.AnonymousAllowed;
+
+import su.tiburon.atlassian.confluence.api.DataCleanUtil;
+
+@Path("/api")
+public class Cleaner {
+ private static final Logger logger = LoggerFactory.getLogger(Cleaner.class);
+
+ private final DataCleanUtil dataCleanUtil;
+ @ConfluenceImport
+ private final PermissionManager permissionManager;
+ @ConfluenceImport
+ private final PageManager pageManager;
+ @ConfluenceImport
+ private final SpaceManager spaceManager;
+ private final static int MAX_LIMIT_FOR_VERSIONS = 1000;
+ private final static int MAX_LIMIT_FOR_TRASH = 100;
+ private final static long NOT_DELETED = 0;
+ private final static String ITEM_TYPE_FOR_SPACE_TRASH = "SpaceTrash";
+ private final static String END_DAYS_FOR_SPACE_TRASH = "Endless";
+
+ @Inject
+ public Cleaner(DataCleanUtil dataCleanUtil, PermissionManager permissionManager, PageManager pageManager, SpaceManager spaceManager) {
+ this.dataCleanUtil = dataCleanUtil;
+ this.permissionManager = permissionManager;
+ this.pageManager = pageManager;
+ this.spaceManager = spaceManager;
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_JSON})
+ @Path("/versions/all")
+ @AnonymousAllowed
+ public Response getAllVersions(@QueryParam("type") String type, @QueryParam("endDays") String endDaysStr, @QueryParam("limit") String limitStr) {
+ // Authentication
+ ConfluenceUser loggedInAppUser = AuthenticatedUserThreadLocal.get();
+ if (!this.permissionManager.isConfluenceAdministrator(loggedInAppUser)) {
+ return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorModel("401 Unauthorized", "Confluence Administrator Permission required!")).build();
+ }
+
+ // Validate Params
+ VersionBaseParam baseParam = new VersionBaseParam(type, endDaysStr, limitStr, MAX_LIMIT_FOR_VERSIONS);
+ if (baseParam.getErrorModel().getMessages().size() > 0) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(baseParam.getErrorModel()).build();
+ }
+
+ // Set up
+ this.dataCleanUtil.setLimit(baseParam.getLimit());
+ this.dataCleanUtil.setCount(0);
+
+ // Main process
+ List spaceModels = this.dataCleanUtil.getAllVersionSummary(baseParam.getEndDays(), baseParam.getType());
+
+ ResponseModel responseModel = new ResponseModel(
+ baseParam.getType(),
+ baseParam.getEndDays(),
+ baseParam.getLimit(),
+ this.dataCleanUtil.getCount(),
+ NOT_DELETED,
+ NOT_DELETED,
+ spaceModels);
+ return Response.ok(responseModel).build();
+ }
+
+ @DELETE
+ @Produces({MediaType.APPLICATION_JSON})
+ @Path("/versions/all")
+ @AnonymousAllowed
+ public Response deleteAllVersions(@QueryParam("type") String type, @QueryParam("endDays") String endDaysStr, @QueryParam("limit") String limitStr) {
+ // Authentication
+ ConfluenceUser loggedInAppUser = AuthenticatedUserThreadLocal.get();
+ if (!this.permissionManager.isConfluenceAdministrator(loggedInAppUser)) {
+ return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorModel("401 Unauthorized", "Confluence Administrator Permission required!")).build();
+ }
+
+ // Validate Params
+ VersionBaseParam baseParam = new VersionBaseParam(type, endDaysStr, limitStr, MAX_LIMIT_FOR_VERSIONS);
+ if (baseParam.getErrorModel().getMessages().size() > 0) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(baseParam.getErrorModel()).build();
+ }
+
+ // Set up
+ this.dataCleanUtil.setLimit(baseParam.getLimit());
+ this.dataCleanUtil.setCount(0);
+
+ // Main process
+ logger.info(MessageFormat.format("User({0}) deleting versions for all spaces..", new Object[] {loggedInAppUser.getName() }));
+ long deleted = this.dataCleanUtil.removeAllVersions(baseParam.getEndDays(), baseParam.getType());
+
+ ResponseModel responseModel = new ResponseModel(
+ baseParam.getType(),
+ baseParam.getEndDays(),
+ baseParam.getLimit(),
+ this.dataCleanUtil.getCount(),
+ this.dataCleanUtil.getCount(),
+ deleted,
+ new MessageModel("Deleted Versions Count - " + deleted));
+ return Response.ok(responseModel).build();
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_JSON})
+ @Path("/versions/space/{spaceKey}")
+ @AnonymousAllowed
+ public Response getSpaceVersionsBySpaceKey(@QueryParam("type") String type, @QueryParam("endDays") String endDaysStr, @QueryParam("limit") String limitStr, @PathParam("spaceKey") String spaceKey) {
+ // Authentication
+ if (StringUtils.isEmpty(spaceKey)) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorModel("400 Bad Request", "Required fields are missing. : spaceKey")).build();
+ }
+ Space space = this.spaceManager.getSpace(spaceKey);
+ if (space == null) {
+ return Response.status(Response.Status.NOT_FOUND).entity(new ErrorModel("404 Not Found", "Space is not exists!")).build();
+ }
+ ConfluenceUser loggedInAppUser = AuthenticatedUserThreadLocal.get();
+ if (!this.permissionManager.hasPermission(loggedInAppUser, Permission.VIEW, space)) {
+ return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorModel("401 Unauthorized", "View Permission denied!")).build();
+ }
+
+ // Validate Params
+ VersionBaseParam baseParam = new VersionBaseParam(type, endDaysStr, limitStr, MAX_LIMIT_FOR_VERSIONS);
+ if (baseParam.getErrorModel().getMessages().size() > 0) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(baseParam.getErrorModel()).build();
+ }
+
+ // Set up
+ this.dataCleanUtil.setLimit(baseParam.getLimit());
+ this.dataCleanUtil.setCount(0);
+
+ // Main process
+ SpaceVersionsModel spaceVersionModel = this.dataCleanUtil.getSpaceVersionSummary(space, baseParam.getEndDays(), baseParam.getType());
+
+ ResponseModel responseModel = new ResponseModel(
+ baseParam.getType(),
+ baseParam.getEndDays(),
+ baseParam.getLimit(),
+ this.dataCleanUtil.getCount(),
+ NOT_DELETED,
+ NOT_DELETED,
+ spaceVersionModel);
+ return Response.ok(responseModel).build();
+ }
+
+ @DELETE
+ @Produces({MediaType.APPLICATION_JSON})
+ @Path("/versions/space/{spaceKey}")
+ @AnonymousAllowed
+ public Response deleteSpaceVersionsBySpaceKey(@QueryParam("type") String type, @QueryParam("endDays") String endDaysStr, @QueryParam("limit") String limitStr, @PathParam("spaceKey") String spaceKey) {
+ // Authentication
+ if (StringUtils.isEmpty(spaceKey)) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorModel("400 Bad Request", "Required fields are missing. : spaceKey")).build();
+ }
+ Space space = this.spaceManager.getSpace(spaceKey);
+ if (space == null) {
+ return Response.status(Response.Status.NOT_FOUND).entity(new ErrorModel("404 Not Found", "Space is not exists!")).build();
+ }
+ ConfluenceUser loggedInAppUser = AuthenticatedUserThreadLocal.get();
+ if (!this.permissionManager.hasPermission(loggedInAppUser, Permission.ADMINISTER, space)) {
+ return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorModel("401 Unauthorized", "Admin Permission denied!")).build();
+ }
+
+ // Validate Params
+ VersionBaseParam baseParam = new VersionBaseParam(type, endDaysStr, limitStr, MAX_LIMIT_FOR_VERSIONS);
+ if (baseParam.getErrorModel().getMessages().size() > 0) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(baseParam.getErrorModel()).build();
+ }
+
+ // Set up
+ this.dataCleanUtil.setLimit(baseParam.getLimit());
+ this.dataCleanUtil.setCount(0);
+
+ // Main process
+ logger.info(MessageFormat.format("User({0}) deleting versions for spaceKey {1}", new Object[] {loggedInAppUser.getName(), spaceKey }));
+ long deleted = this.dataCleanUtil.removeSpaceVersions(space, baseParam.getEndDays(), baseParam.getType());
+
+ ResponseModel responseModel = new ResponseModel(
+ baseParam.getType(),
+ baseParam.getEndDays(),
+ baseParam.getLimit(),
+ this.dataCleanUtil.getCount(),
+ this.dataCleanUtil.getCount(),
+ deleted,
+ new MessageModel("Deleted Versions Count - " + deleted));
+ return Response.ok(responseModel).build();
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_JSON})
+ @Path("/versions/page/{pageId}")
+ @AnonymousAllowed
+ public Response getPageVersionsByPageId(@QueryParam("type") String type, @QueryParam("endDays") String endDaysStr, @QueryParam("limit") String limitStr, @PathParam("pageId") long pageId) {
+ // Authentication
+ if (pageId <= 0L) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorModel("400 Bad Request", "Required fields are missing. : spaceKey")).build();
+ }
+ Page page = this.pageManager.getPage(pageId);
+ if (page == null) {
+ return Response.status(Response.Status.NOT_FOUND).entity(new ErrorModel("404 Not Found", "Space is not exists!")).build();
+ }
+ ConfluenceUser loggedInAppUser = AuthenticatedUserThreadLocal.get();
+ if (!this.permissionManager.hasPermission(loggedInAppUser, Permission.VIEW, page)) {
+ return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorModel("401 Unauthorized", "View Permission denied!")).build();
+ }
+
+ // Validate Params
+ VersionBaseParam baseParam = new VersionBaseParam(type, endDaysStr, limitStr, MAX_LIMIT_FOR_VERSIONS);
+ if (baseParam.getErrorModel().getMessages().size() > 0) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(baseParam.getErrorModel()).build();
+ }
+
+ // Set up
+ this.dataCleanUtil.setLimit(baseParam.getLimit());
+ this.dataCleanUtil.setCount(0);
+
+ // Main process
+ PageVersionsModel pageVersionsModel = this.dataCleanUtil.getPageVersionSummary(page, baseParam.getEndDays(), baseParam.getType());
+
+ ResponseModel responseModel = new ResponseModel(
+ baseParam.getType(),
+ baseParam.getEndDays(),
+ baseParam.getLimit(),
+ this.dataCleanUtil.getCount(),
+ NOT_DELETED,
+ NOT_DELETED,
+ pageVersionsModel);
+ return Response.ok(responseModel).build();
+ }
+
+ @DELETE
+ @Produces({MediaType.APPLICATION_JSON})
+ @Path("/versions/page/{pageId}")
+ @AnonymousAllowed
+ public Response deletePageVersionsByPageId(@QueryParam("type") String type, @QueryParam("endDays") String endDaysStr, @QueryParam("limit") String limitStr, @PathParam("pageId") long pageId) {
+ // Authentication
+ if (pageId <= 0L) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorModel("400 Bad Request", "Required fields are missing. : spaceKey")).build();
+ }
+ Page page = this.pageManager.getPage(pageId);
+ if (page == null) {
+ return Response.status(Response.Status.NOT_FOUND).entity(new ErrorModel("404 Not Found", "Space is not exists!")).build();
+ }
+ ConfluenceUser loggedInAppUser = AuthenticatedUserThreadLocal.get();
+ if (!this.permissionManager.hasPermission(loggedInAppUser, Permission.ADMINISTER, page)) {
+ return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorModel("401 Unauthorized", "Admin Permission denied!")).build();
+ }
+
+ // Validate Params
+ VersionBaseParam baseParam = new VersionBaseParam(type, endDaysStr, limitStr, MAX_LIMIT_FOR_VERSIONS);
+ if (baseParam.getErrorModel().getMessages().size() > 0) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(baseParam.getErrorModel()).build();
+ }
+
+ // Set up
+ this.dataCleanUtil.setLimit(baseParam.getLimit());
+ this.dataCleanUtil.setCount(0);
+
+ // Main process
+ logger.info(MessageFormat.format("User({0}) deleting page versions for pageId {1}", new Object[] {loggedInAppUser.getName(), Long.valueOf(pageId) }));
+ long deleted = this.dataCleanUtil.removePageVersions(page, baseParam.getEndDays(), baseParam.getType());
+
+ ResponseModel responseModel = new ResponseModel(
+ baseParam.getType(),
+ baseParam.getEndDays(),
+ baseParam.getLimit(),
+ this.dataCleanUtil.getCount(),
+ this.dataCleanUtil.getCount(),
+ deleted,
+ new MessageModel("Deleted Versions Count - " + deleted));
+ return Response.ok(responseModel).build();
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_JSON})
+ @Path("/trash/all")
+ @AnonymousAllowed
+ public Response getAllGarbages(@QueryParam("limit") String limitStr) {
+ // Authentication
+ ConfluenceUser loggedInAppUser = AuthenticatedUserThreadLocal.get();
+ if (!this.permissionManager.isConfluenceAdministrator(loggedInAppUser)) {
+ return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorModel("401 Unauthorized", "Confluence Administrator Permission required!")).build();
+ }
+
+ // Validate Params
+ TrashBaseParam baseParam = new TrashBaseParam(ITEM_TYPE_FOR_SPACE_TRASH, END_DAYS_FOR_SPACE_TRASH, limitStr, MAX_LIMIT_FOR_TRASH);
+ if (baseParam.getErrorModel().getMessages().size() > 0) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(baseParam.getErrorModel()).build();
+ }
+
+ // Set up
+ this.dataCleanUtil.setLimit(baseParam.getLimit());
+ this.dataCleanUtil.setCount(0);
+
+ // Main process
+ List trashModels = this.dataCleanUtil.getAllTrashSummary();
+
+ ResponseModel responseModel = new ResponseModel(
+ baseParam.getType(),
+ baseParam.getEndDays(),
+ baseParam.getLimit(),
+ this.dataCleanUtil.getCount(),
+ NOT_DELETED,
+ NOT_DELETED,
+ trashModels);
+ return Response.ok(responseModel).build();
+ }
+
+ @DELETE
+ @Produces({MediaType.APPLICATION_JSON})
+ @Path("/trash/all")
+ @AnonymousAllowed
+ public Response deleteAllGarbages(@QueryParam("limit") String limitStr) {
+ // Authentication
+ ConfluenceUser loggedInAppUser = AuthenticatedUserThreadLocal.get();
+ if (!this.permissionManager.isConfluenceAdministrator(loggedInAppUser)) {
+ return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorModel("401 Unauthorized", "Confluence Administrator Permission required!")).build();
+ }
+
+ // Validate Params
+ TrashBaseParam baseParam = new TrashBaseParam(ITEM_TYPE_FOR_SPACE_TRASH, END_DAYS_FOR_SPACE_TRASH, limitStr, MAX_LIMIT_FOR_TRASH);
+ if (baseParam.getErrorModel().getMessages().size() > 0) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(baseParam.getErrorModel()).build();
+ }
+
+ // Set up
+ this.dataCleanUtil.setLimit(baseParam.getLimit());
+ this.dataCleanUtil.setCount(0);
+
+ // Main process
+ logger.info(MessageFormat.format("User({0}) deleting space trash for all", new Object[] {loggedInAppUser.getName() }));
+ long deleted = this.dataCleanUtil.removeAllTrash();
+
+ ResponseModel responseModel = new ResponseModel(
+ baseParam.getType(),
+ baseParam.getEndDays(),
+ baseParam.getLimit(),
+ this.dataCleanUtil.getCount(),
+ this.dataCleanUtil.getCount(),
+ deleted,
+ new MessageModel("Deleted Trash Items Count - " + deleted));
+ return Response.ok(responseModel).build();
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_JSON})
+ @Path("/trash/space/{spaceKey}")
+ @AnonymousAllowed
+ public Response getSpaceGarbagesBySpaceKey(@QueryParam("limit") String limitStr, @PathParam("spaceKey") String spaceKey) {
+ // Authentication
+ if (StringUtils.isEmpty(spaceKey)) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorModel("400 Bad Request", "Required fields are missing. : spaceKey")).build();
+ }
+ Space space = this.spaceManager.getSpace(spaceKey);
+ if (space == null) {
+ return Response.status(Response.Status.NOT_FOUND).entity(new ErrorModel("404 Not Found", "Space is not exists!")).build();
+ }
+ ConfluenceUser loggedInAppUser = AuthenticatedUserThreadLocal.get();
+ if (!this.permissionManager.hasPermission(loggedInAppUser, Permission.VIEW, space)) {
+ return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorModel("401 Unauthorized", "View Permission denied!")).build();
+ }
+
+ // Validate Params
+ TrashBaseParam baseParam = new TrashBaseParam(ITEM_TYPE_FOR_SPACE_TRASH, END_DAYS_FOR_SPACE_TRASH, limitStr, MAX_LIMIT_FOR_TRASH);
+ if (baseParam.getErrorModel().getMessages().size() > 0) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(baseParam.getErrorModel()).build();
+ }
+
+ // Set up
+ this.dataCleanUtil.setLimit(baseParam.getLimit());
+ this.dataCleanUtil.setCount(0);
+
+ // Main process
+ SpaceTrashModel spaceTrashModel = this.dataCleanUtil.getSpaceTrashSummary(space);
+
+ ResponseModel responseModel = new ResponseModel(
+ baseParam.getType(),
+ baseParam.getEndDays(),
+ baseParam.getLimit(),
+ this.dataCleanUtil.getCount(),
+ NOT_DELETED,
+ NOT_DELETED,
+ spaceTrashModel);
+ return Response.ok(responseModel).build();
+ }
+
+ @DELETE
+ @Produces({MediaType.APPLICATION_JSON})
+ @Path("/trash/space/{spaceKey}")
+ @AnonymousAllowed
+ public Response deleteSpaceGarbagesBySpaceKey(@QueryParam("limit") String limitStr, @PathParam("spaceKey") String spaceKey) {
+ // Authentication
+ if (StringUtils.isEmpty(spaceKey)) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorModel("400 Bad Request", "Required fields are missing. : spaceKey")).build();
+ }
+ Space space = this.spaceManager.getSpace(spaceKey);
+ if (space == null) {
+ return Response.status(Response.Status.NOT_FOUND).entity(new ErrorModel("404 Not Found", "Space is not exists!")).build();
+ }
+ ConfluenceUser loggedInAppUser = AuthenticatedUserThreadLocal.get();
+ if (!this.permissionManager.hasPermission(loggedInAppUser, Permission.ADMINISTER, space)) {
+ return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorModel("401 Unauthorized", "Admin Permission denied!")).build();
+ }
+
+ // Validate Params
+ TrashBaseParam baseParam = new TrashBaseParam(ITEM_TYPE_FOR_SPACE_TRASH, END_DAYS_FOR_SPACE_TRASH, limitStr, MAX_LIMIT_FOR_TRASH);
+ if (baseParam.getErrorModel().getMessages().size() > 0) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(baseParam.getErrorModel()).build();
+ }
+
+ // Set up
+ this.dataCleanUtil.setLimit(baseParam.getLimit());
+ this.dataCleanUtil.setCount(0);
+
+ // Main process
+ logger.info(MessageFormat.format("User({0}) deleting space trash for spaceKey {1}", new Object[] {loggedInAppUser.getName(), Long.valueOf(spaceKey) }));
+ int deleted = 0;
+ deleted = this.dataCleanUtil.removeSpaceTrash(space);
+
+ ResponseModel responseModel = new ResponseModel(
+ baseParam.getType(),
+ baseParam.getEndDays(),
+ baseParam.getLimit(),
+ this.dataCleanUtil.getCount(),
+ this.dataCleanUtil.getCount(),
+ deleted,
+ new MessageModel("Deleted Trash Items Count - " + deleted));
+ return Response.ok(responseModel).build();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/DirectoryModel.java b/src/main/java/su/tiburon/atlassian/confluence/rest/DirectoryModel.java
new file mode 100644
index 0000000..197cf39
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/DirectoryModel.java
@@ -0,0 +1,35 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.atlassian.crowd.embedded.api.DirectoryType;
+
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class DirectoryModel {
+
+ @XmlElement
+ private Long id;
+
+ @XmlElement
+ private DirectoryType type;
+
+ @XmlElement
+ private Boolean issynchronising;
+
+ public DirectoryModel() {
+ this.id = null;
+ this.type = null;
+ this.issynchronising = false;
+ }
+
+ public DirectoryModel(Long id, DirectoryType type, Boolean issynchronising) {
+ this.id = id;
+ this.type = type;
+ this.issynchronising = issynchronising;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/DirectoryService.java b/src/main/java/su/tiburon/atlassian/confluence/rest/DirectoryService.java
new file mode 100644
index 0000000..f124d9c
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/DirectoryService.java
@@ -0,0 +1,80 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.QueryParam;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.atlassian.confluence.security.PermissionManager;
+import com.atlassian.confluence.user.AuthenticatedUserThreadLocal;
+import com.atlassian.confluence.user.ConfluenceUser;
+import com.atlassian.plugin.spring.scanner.annotation.imports.ConfluenceImport;
+import com.atlassian.plugins.rest.common.security.AnonymousAllowed;
+import com.atlassian.crowd.embedded.api.CrowdDirectoryService;
+import com.atlassian.crowd.embedded.api.Directory;
+
+@Path("/directory")
+@AnonymousAllowed
+@Produces(MediaType.APPLICATION_JSON)
+public class DirectoryService {
+ private static final Logger logger = LoggerFactory.getLogger(DirectoryService.class);
+
+ @ConfluenceImport
+ private final PermissionManager permissionManager;
+
+ @ConfluenceImport
+ private final CrowdDirectoryService crowdDirectoryService;
+
+ @Inject
+ public DirectoryService(PermissionManager permissionManager, CrowdDirectoryService crowdDirectoryService) {
+ this.permissionManager = permissionManager;
+ this.crowdDirectoryService = crowdDirectoryService;
+ }
+
+ @GET
+ public Response getDir() {
+ // Authentication
+ ConfluenceUser loggedInAppUser = AuthenticatedUserThreadLocal.get();
+ if (!this.permissionManager.isConfluenceAdministrator(loggedInAppUser)) {
+ return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorModel("401 Unauthorized", "Confluence Administrator Permission required!")).build();
+ }
+ logger.info(MessageFormat.format("User({0}) requesting infodmation about CUDs", new Object[] {loggedInAppUser.getName() }));
+
+ Collection coll = new ArrayList();
+
+ for (Directory dsa : crowdDirectoryService.findAllDirectories()) {
+ coll.add(new DirectoryModel(dsa.getId(),dsa.getType(),crowdDirectoryService.isDirectorySynchronising(dsa.getId())));
+ }
+ return Response.ok(coll).build();
+ }
+
+ @PUT
+ public Response syncDir(@QueryParam("id") Long dirId) {
+
+ // Authentication
+ ConfluenceUser loggedInAppUser = AuthenticatedUserThreadLocal.get();
+ if (!this.permissionManager.isConfluenceAdministrator(loggedInAppUser)) {
+ return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorModel("401 Unauthorized", "Confluence Administrator Permission required!")).build();
+ }
+
+ crowdDirectoryService.synchroniseDirectory(dirId, true);
+
+ Collection coll = new ArrayList();
+
+ for (Directory dsa : crowdDirectoryService.findAllDirectories()) {
+ coll.add(new DirectoryModel(dsa.getId(),dsa.getType(),crowdDirectoryService.isDirectorySynchronising(dsa.getId())));
+ }
+ return Response.ok(coll).build();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/ErrorModel.java b/src/main/java/su/tiburon/atlassian/confluence/rest/ErrorModel.java
new file mode 100644
index 0000000..bb58bcb
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/ErrorModel.java
@@ -0,0 +1,52 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ErrorModel {
+
+ @XmlElement(name = "statusCode")
+ private String statusCode;
+
+ @XmlElementWrapper
+ @XmlElement(name="message")
+ public List messages;
+
+ public ErrorModel() {
+ this.statusCode = "";
+ this.messages = new ArrayList();
+ }
+
+ public ErrorModel(String statusCode, String messages) {
+ this.statusCode = statusCode;
+ this.messages = new ArrayList();
+ this.addMessage(messages);
+ }
+
+ public String getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(String statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ public List getMessages() {
+ return messages;
+ }
+
+ public void setMessages(List messages) {
+ this.messages = messages;
+ }
+
+ public void addMessage(String message) {
+ this.messages.add(new MessageModel(message));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/MessageModel.java b/src/main/java/su/tiburon/atlassian/confluence/rest/MessageModel.java
new file mode 100644
index 0000000..26cb49a
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/MessageModel.java
@@ -0,0 +1,29 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class MessageModel {
+
+ @XmlElement(name = "message")
+ private String message;
+
+ public MessageModel() {
+ this.message = "";
+ }
+
+ public MessageModel(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/PageVersionsModel.java b/src/main/java/su/tiburon/atlassian/confluence/rest/PageVersionsModel.java
new file mode 100644
index 0000000..447855e
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/PageVersionsModel.java
@@ -0,0 +1,109 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class PageVersionsModel {
+
+ @XmlElement
+ public String id;
+ @XmlElement
+ public String title;
+ @XmlElement
+ public long totalVersionCount;
+ @XmlElement
+ public int versionCount;
+ @XmlElement
+ public String lastModifier;
+ @XmlElement
+ public String lastModified;
+ @XmlElementWrapper
+ @XmlElement(name="attachment")
+ public List attachments;
+
+ public PageVersionsModel() {
+ this.id = "";
+ this.title = "";
+ this.versionCount = -1;
+ this.totalVersionCount = -1;
+ this.lastModifier = "";
+ this.lastModified = "";
+ this.attachments = new ArrayList();
+ }
+
+ public PageVersionsModel(Long id, String title, long totalVersionCount, int versionCount, String lastModifier, Date lastModified, List attachments) {
+ this.id = String.valueOf(id);
+ this.title = title;
+ this.totalVersionCount = totalVersionCount;
+ this.versionCount = versionCount;
+ this.lastModifier = lastModifier;
+ this.lastModified = String.valueOf(lastModified);
+ this.attachments = attachments;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = String.valueOf(id);
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getVersionCount() {
+ return versionCount;
+ }
+
+ public void setVersionCount(int versionCount) {
+ this.versionCount = versionCount;
+ }
+
+ public String getLastModifier() {
+ return lastModifier;
+ }
+
+ public void setLastModifier(String lastModifier) {
+ this.lastModifier = lastModifier;
+ }
+
+ public String getLastModified() {
+ return lastModified;
+ }
+
+ public void setLastModified(Date lastModified) {
+ this.lastModified = String.valueOf(lastModified);
+ }
+
+ public List getAttachments() {
+ return attachments;
+ }
+
+ public void setAttachments(List attachments) {
+ this.attachments = attachments;
+ }
+
+ public long getTotalVersionCount() {
+ return this.totalVersionCount;
+
+ }
+
+ public void setTotalVersionCount(long totalVersionCount) {
+ this.totalVersionCount = totalVersionCount;
+
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/ResponseModel.java b/src/main/java/su/tiburon/atlassian/confluence/rest/ResponseModel.java
new file mode 100644
index 0000000..5b48893
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/ResponseModel.java
@@ -0,0 +1,103 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ResponseModel {
+
+ @XmlElement
+ public String itemType;
+ @XmlElement
+ public String endDays;
+ @XmlElement
+ public int itemCountLimit;
+ @XmlElement
+ public int targetItemCount;
+ @XmlElement
+ public long deletedItemCount;
+ @XmlElement
+ public long deletedVersionCount;
+ @XmlElement
+ public Object result;
+
+ public ResponseModel(String itemType, int endDays, int itemCountLimit, int targetItemCount, long deletedItemCount, long deletedVersionCount, Object result) {
+ this.itemType = itemType;
+ this.endDays = String.valueOf(endDays);
+ this.itemCountLimit = itemCountLimit;
+ this.targetItemCount = targetItemCount;
+ this.deletedItemCount = deletedItemCount;
+ this.deletedVersionCount = deletedVersionCount;
+ this.result = result;
+ }
+
+ public ResponseModel(String itemType, String endDaysStr, int itemCountLimit, int targetItemCount, long deletedItemCount, long deletedVersionCount, Object result) {
+ this.itemType = itemType;
+ this.endDays = endDaysStr;
+ this.itemCountLimit = itemCountLimit;
+ this.targetItemCount = targetItemCount;
+ this.deletedItemCount = deletedItemCount;
+ this.deletedVersionCount = deletedVersionCount;
+ this.result = result;
+ }
+
+ public String getItemType() {
+ return itemType;
+ }
+
+ public void setItemType(String itemType) {
+ this.itemType = itemType;
+ }
+
+ public String getEndDays() {
+ return endDays;
+ }
+
+ public void setEndDays(String endDays) {
+ this.endDays = endDays;
+ }
+
+ public int getItemCountLimit() {
+ return itemCountLimit;
+ }
+
+ public void setItemCountLimit(int itemCountLimit) {
+ this.itemCountLimit = itemCountLimit;
+ }
+
+ public long getTargetItemCount() {
+ return targetItemCount;
+ }
+
+ public void setTargetItemCount(int targetItemCount) {
+ this.targetItemCount = targetItemCount;
+ }
+
+ public long getDeletedItemCount() {
+ return deletedItemCount;
+ }
+
+ public void setDeletedItemCount(long deletedItemCount) {
+ this.deletedItemCount = deletedItemCount;
+ }
+
+ public long getDeletedVersionCount() {
+ return deletedVersionCount;
+ }
+
+ public void setDeletedVersionCount(long deletedVersionCount) {
+ this.deletedVersionCount = deletedVersionCount;
+ }
+
+ public Object getResult() {
+ return result;
+ }
+
+ public void setResult(Object result) {
+ this.result = result;
+ }
+
+}
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/SpaceTrashModel.java b/src/main/java/su/tiburon/atlassian/confluence/rest/SpaceTrashModel.java
new file mode 100644
index 0000000..2993160
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/SpaceTrashModel.java
@@ -0,0 +1,53 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class SpaceTrashModel {
+
+ @XmlElement
+ public String spaceKey;
+ @XmlElement
+ public String title;
+ @XmlElement
+ public int numberOfItemsInTrash;
+
+ public SpaceTrashModel() {
+ this.spaceKey = "";
+ this.title = "";
+ this.numberOfItemsInTrash = 0;
+ }
+
+ public SpaceTrashModel(String spaceKey, String title, int numberOfItemsInTrash) {
+ this.spaceKey = spaceKey;
+ this.title = title;
+ this.numberOfItemsInTrash = numberOfItemsInTrash;
+ }
+
+ public String getSpaceKey() {
+ return spaceKey;
+ }
+
+ public void setSpaceKey(String spaceKey) {
+ this.spaceKey = spaceKey;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getNumberOfItemsInTrash() {
+ return numberOfItemsInTrash;
+ }
+
+ public void setNumberOfItemsInTrash(int numberOfItemsInTrash) {
+ this.numberOfItemsInTrash = numberOfItemsInTrash;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/SpaceVersionsModel.java b/src/main/java/su/tiburon/atlassian/confluence/rest/SpaceVersionsModel.java
new file mode 100644
index 0000000..a4157f9
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/SpaceVersionsModel.java
@@ -0,0 +1,70 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class SpaceVersionsModel {
+
+ @XmlElement
+ public String spaceKey;
+ @XmlElement
+ public String title;
+ @XmlElement
+ public long totalVersionCount;
+ @XmlElementWrapper
+ @XmlElement(name="page")
+ public List pages;
+
+ public SpaceVersionsModel() {
+ this.spaceKey = "";
+ this.title = "";
+ this.totalVersionCount = -1;
+ this.pages = new ArrayList();
+ }
+
+ public SpaceVersionsModel(String spaceKey, String title, long totalVersionCount, List pages) {
+ this.spaceKey = spaceKey;
+ this.title = title;
+ this.totalVersionCount = totalVersionCount;
+ this.pages = pages;
+ }
+
+ public String getSpaceKey() {
+ return spaceKey;
+ }
+
+ public void setSpaceKey(String spaceKey) {
+ this.spaceKey = spaceKey;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public long getTotalVersionCount() {
+ return totalVersionCount;
+ }
+
+ public void setTotalVersionCount(long totalVersionCount) {
+ this.totalVersionCount = totalVersionCount;
+ }
+
+ public List getPages() {
+ return pages;
+ }
+
+ public void setPages(List pages) {
+ this.pages = pages;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/TrashBaseParam.java b/src/main/java/su/tiburon/atlassian/confluence/rest/TrashBaseParam.java
new file mode 100644
index 0000000..84d0b2d
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/TrashBaseParam.java
@@ -0,0 +1,71 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import org.springframework.util.StringUtils;
+
+public class TrashBaseParam {
+
+ private String type;
+ private String endDays;
+ private int limit;
+ private ErrorModel errorModel;
+
+
+ public TrashBaseParam(String type, String endDaysStr, String limitStr, int maxLimit) {
+ this.errorModel = new ErrorModel();
+ this.type = type;
+ this.endDays = endDaysStr;
+ validateLimit(limitStr, maxLimit);
+
+ }
+
+ public String getType() {
+ return type;
+ }
+
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+
+ public String getEndDays() {
+ return endDays;
+ }
+
+
+ public void setEndDays(String endDays) {
+ this.endDays = endDays;
+ }
+
+
+ public int getLimit() {
+ return limit;
+ }
+
+
+ public void setLimit(int limit) {
+ this.limit = limit;
+ }
+
+
+ public ErrorModel getErrorModel() {
+ return errorModel;
+ }
+
+ private void validateLimit(String limitStr, int maxLimit) {
+ if(StringUtils.isEmpty(limitStr)) {
+ limitStr = String.valueOf(maxLimit);
+ }
+ try {
+ this.limit = Integer.parseInt(limitStr);
+ if (limit < 1 || limit > maxLimit) {
+ this.errorModel.setStatusCode("400 Bad Request");
+ this.errorModel.addMessage("limit is invalid. : limit=1~" + String.valueOf(maxLimit));
+ }
+ } catch (NumberFormatException e) {
+ this.errorModel.setStatusCode("400 Bad Request");
+ this.errorModel.addMessage("limit is invalid. : limit=1~" + String.valueOf(maxLimit));
+ }
+ }
+
+}
diff --git a/src/main/java/su/tiburon/atlassian/confluence/rest/VersionBaseParam.java b/src/main/java/su/tiburon/atlassian/confluence/rest/VersionBaseParam.java
new file mode 100644
index 0000000..77132d9
--- /dev/null
+++ b/src/main/java/su/tiburon/atlassian/confluence/rest/VersionBaseParam.java
@@ -0,0 +1,99 @@
+package su.tiburon.atlassian.confluence.rest;
+
+import org.springframework.util.StringUtils;
+
+public class VersionBaseParam {
+
+ private String type;
+ private int endDays;
+ private int limit;
+ private ErrorModel errorModel;
+
+
+ public VersionBaseParam(String type, String endDaysStr, String limitStr, int maxLimit) {
+ this.errorModel = new ErrorModel();
+ validateType(type);
+ validateEndDays(endDaysStr);
+ validateLimit(limitStr, maxLimit);
+
+ }
+
+ public String getType() {
+ return type;
+ }
+
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+
+ public int getEndDays() {
+ return endDays;
+ }
+
+
+ public void setEndDays(int endDays) {
+ this.endDays = endDays;
+ }
+
+
+ public int getLimit() {
+ return limit;
+ }
+
+
+ public void setLimit(int limit) {
+ this.limit = limit;
+ }
+
+
+ public ErrorModel getErrorModel() {
+ return errorModel;
+ }
+
+ private void validateType(String type) {
+ if(StringUtils.isEmpty(type)) {
+ type = "all";
+ }
+ if ("all".equals(type) || "page".equals(type) || "attachment".equals(type)) {
+ this.type = type;
+ } else {
+ this.errorModel.setStatusCode("400 Bad Request");
+ this.errorModel.addMessage("type is invalid. : type=all or type=page or type=attachment");
+ }
+ }
+
+ private void validateEndDays(String endDaysStr) {
+ if(StringUtils.isEmpty(endDaysStr)) {
+ endDaysStr = "0";
+ }
+ try {
+ this.endDays = Integer.parseInt(endDaysStr);
+ if (endDays < 0 ) {
+ this.errorModel.setStatusCode("400 Bad Request");
+ this.errorModel.addMessage("endDays is invalid. : endDays=0~ ");
+ }
+ } catch (NumberFormatException e) {
+ this.errorModel.setStatusCode("400 Bad Request");
+ this.errorModel.addMessage("endDays is invalid. : endDays=0~ ");
+ }
+ }
+
+ private void validateLimit(String limitStr, int maxLimit) {
+ if(StringUtils.isEmpty(limitStr)) {
+ limitStr = String.valueOf(maxLimit);
+ }
+ try {
+ this.limit = Integer.parseInt(limitStr);
+ if (limit < 1 || limit > maxLimit) {
+ this.errorModel.setStatusCode("400 Bad Request");
+ this.errorModel.addMessage("limit is invalid. : limit=1~" + String.valueOf(maxLimit));
+ }
+ } catch (NumberFormatException e) {
+ this.errorModel.setStatusCode("400 Bad Request");
+ this.errorModel.addMessage("limit is invalid. : limit=1~" + String.valueOf(maxLimit));
+ }
+ }
+
+}
diff --git a/src/main/resources/META-INF/spring/plugin-context.xml b/src/main/resources/META-INF/spring/plugin-context.xml
new file mode 100644
index 0000000..82bc606
--- /dev/null
+++ b/src/main/resources/META-INF/spring/plugin-context.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/atlassian-plugin.xml b/src/main/resources/atlassian-plugin.xml
new file mode 100644
index 0000000..c1f5da2
--- /dev/null
+++ b/src/main/resources/atlassian-plugin.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ ${project.description}
+ ${project.version}
+
+ images/logo_octo_375_293.png
+ images/logo_octo_375_293.png
+
+
+
+
+
+ com.atlassian.auiplugin:ajs
+
+
+
+ rest-extender
+
+
+ Rest Extender Plugin
+
+
diff --git a/src/main/resources/css/rest-extender.css b/src/main/resources/css/rest-extender.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/resources/images/logo_octo_375_293.png b/src/main/resources/images/logo_octo_375_293.png
new file mode 100644
index 0000000..543fe87
Binary files /dev/null and b/src/main/resources/images/logo_octo_375_293.png differ
diff --git a/src/main/resources/js/rest-extender.js b/src/main/resources/js/rest-extender.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/resources/rest-extender.properties b/src/main/resources/rest-extender.properties
new file mode 100644
index 0000000..5a6bf7f
--- /dev/null
+++ b/src/main/resources/rest-extender.properties
@@ -0,0 +1,3 @@
+#put any key/value pairs here
+rest-extender.name=REST Extender
+rest-extender.description=Confluence REST API extender