+* A script that should be used as a Rest Endpoint script in ScriptRunner for Confluence.
+* This script creates the specified page tree structure.
+* The structure can optionally be based on templates and includes parameters for Title, body content, child pages and labels.
+import com.atlassian.confluence.core.BodyContent
+import com.atlassian.confluence.core.BodyType
+import com.atlassian.confluence.core.DefaultSaveContext
+import com.atlassian.confluence.labels.Label
+import com.atlassian.confluence.labels.LabelManager
+import com.atlassian.confluence.labels.Labelable
+import com.atlassian.confluence.pages.Page
+import com.atlassian.confluence.pages.PageManager
+import com.atlassian.confluence.pages.templates.PageTemplate
+import com.atlassian.confluence.pages.templates.PageTemplateManager
+import com.atlassian.confluence.spaces.Space
+import com.atlassian.confluence.spaces.SpaceManager
+import com.atlassian.confluence.user.AuthenticatedUserThreadLocal
+import com.atlassian.sal.api.component.ComponentLocator
+import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
+import groovy.json.JsonOutput
+import groovy.transform.BaseScript
+import javax.ws.rs.core.MultivaluedMap
+import javax.ws.rs.core.Response
+// The page tree configuration. The respective fields like content, template and label are optional. The page field defines child pages.
+ content: "Parent Page Content",
+ title : "Child Page 1",
+ title : "Child Page 2",
+ label : ["label1", "label2"]
+// Configure the manager classes
+spaceMgr = ComponentLocator.getComponent(SpaceManager.class)
+pageMgr = ComponentLocator.getComponent(PageManager.class) as PageManager
+pageTemplateMgr = ComponentLocator.getComponent(PageTemplateManager.class) as PageTemplateManager
+labelMgr = ComponentLocator.getComponent(LabelManager.class)
+@BaseScript CustomEndpointDelegate delegate
+createPagesWithLabels(httpMethod: "GET", groups: ["confluence-administrators"]) { MultivaluedMap queryParams, String body ->
+ def spaceId = queryParams.get("spaceId")[0] as String
+ title: "Pages Created",
+ body : "You have created page for this space ${spaceId}"
+ } catch (Exception e) {
+ title: "An Error Occurred",
+ body : "There was an error trying to create the pages. Please see the log for further details."
+ Response.ok(JsonOutput.toJson(flag)).build()
+ * Create the desired page structure for demonstration.
+ * @param spaceId The ID of the space to add pages for.
+private void createPages(String spaceId) throws Exception {
+ def space = spaceMgr.getSpace(spaceId) as Space
+ def spaceHomePage = space.getHomePage() as Page
+ spec.each { pageSpec ->
+ createPage(spaceHomePage, space, pageSpec)
+ * Create a page using the given page specification (pageSpec). This spec dictates the title of the page, the template
+ * to be used to populate it (if any) and if required, the specification of any child pages.
+ * @param parent The parent page for the page we're about to create.
+ * @param space The space that the page should be created in.
+ * @param pageSpec The specification for the pages to create.
+private void createPage(Page parent, Space space, Map pageSpec) {
+ def testPageTitle = pageSpec.title as String
+ def basicContent = pageSpec.content as String
+ def labelTxt = pageSpec.label as List<String>
+ def templateId = pageSpec.template as Long
+ // Generate content - with a default in case we can't find the template id
+ def content = "Please enter some content.."
+ String templateContent = getTemplateContent(templateId)
+ content = templateContent
+ } else if (basicContent) {
+ def createdPage = createBasicPage(space, testPageTitle, content)
+ linkPages(parent, createdPage)
+ pageMgr.saveContentEntity(createdPage, DefaultSaveContext.SUPPRESS_NOTIFICATIONS)
+ log.debug("Created page ${testPageTitle} successfully")
+ } catch (Exception e) {
+ log.error("Unable to create page ${testPageTitle}", e)
+ pageSpec.page.each { childPageSpec ->
+ // Do this thing, but alter the parent
+ createPage(createdPage, space, childPageSpec as Map)
+ labelTxt?.each { label ->
+ addLabel(createdPage.getId(), label)
+ * Get the content from the template to populate the page with.
+ * @param templateId The ID of the template we wish to use.
+ * @return The template body content.
+private String getTemplateContent(long templateId) {
+ PageTemplate template = pageTemplateMgr.getPageTemplate(templateId)
+ * Create a basic page. This is not linked in any hierarchy.
+ * @param space The space that this page belongs to.
+ * @param title The title of the page we are creating.
+ * @return The create page object.
+private Page createBasicPage(Space space, String title, String content) {
+ // Set the page content
+ def bodyContent = new BodyContent(page, content, BodyType.XHTML)
+ page.setBodyContent(bodyContent)
+ // Set the user calling the endpoint as the creator
+ page.setCreator(AuthenticatedUserThreadLocal.get())
+ * Link a parent and a child page together. This method creates a bi-directional relationship between the two pages.
+ * @param parent The parent page that we wish to link.
+ * @param child The child page that we wish to link.
+private void linkPages(Page parent, Page child) {
+ // Set the parent page on the child
+ child.setParentPage(parent)
+ // Set the child page on the parent
+ * Add the label to the page for the given page ID.
+ * @param pageId The page ID for adding the label to the page.
+ * @param label The label we want to add to the page.
+private void addLabel(long pageId, String label) {
+ Page page = pageMgr.getPage(pageId)
+ (labelMgr as LabelManager).addLabel(page as Labelable, new Label(label))