aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Foster2012-10-15 18:58:08 (EDT)
committerBob Foster2012-10-15 18:58:08 (EDT)
commit2031586217ef59a4c5c7b47c0100c017ddc31656 (patch)
treea48d67d0c91593b1d8548391a8924b45a907d391
parent6f767243d935409ec2b63067adef4cf9e8222c2b (diff)
downloadorg.eclipse.hudson.stapler-2031586217ef59a4c5c7b47c0100c017ddc31656.zip
org.eclipse.hudson.stapler-2031586217ef59a4c5c7b47c0100c017ddc31656.tar.gz
org.eclipse.hudson.stapler-2031586217ef59a4c5c7b47c0100c017ddc31656.tar.bz2
Add xpath-servicerefs/changes/24/8224/1
-rw-r--r--xpath-service/.gitignore1
-rw-r--r--xpath-service/README.md15
-rw-r--r--xpath-service/pom.xml78
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/Stylesheet.java72
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/StylesheetAPI.java39
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/StylesheetAPIFactory.java24
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/XNamespaceContext.java80
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/XPath.java100
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/XPathAPI.java53
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/XPathAPIFactory.java24
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/XPathException.java31
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/XVariableContext.java27
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/impl/Dom2Dom.java342
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/impl/Pair.java40
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/impl/Rewriter.java279
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/impl/StylesheetJavaImpl.java47
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/impl/Trim.java96
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/impl/XDocumentType.java304
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/impl/XNamedNodeMap.java104
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/impl/XNamespaceAttribute.java212
-rw-r--r--xpath-service/src/main/java/org/hudsonci/xpath/impl/XPathJavaImpl.java365
-rw-r--r--xpath-service/src/test/java/org/hudsonci/xpath/TestDocumentSupport.java106
-rw-r--r--xpath-service/src/test/java/org/hudsonci/xpath/TestDom4jToXDom.java296
-rw-r--r--xpath-service/src/test/java/org/hudsonci/xpath/TestXPathOnXNode.java122
-rw-r--r--xpath-service/src/test/java/org/hudsonci/xpath/XMLCompare.java266
-rw-r--r--xpath-service/src/test/java/org/hudsonci/xpath/XMLParser.java61
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/_api.jelly36
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/_cli.jelly35
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/_entryForm.jelly81
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/_new.jelly44
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/_restart.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/_safeRestart.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/_script.jelly59
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/_scriptText.jelly23
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/accessDenied.jelly52
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/actions.jelly29
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/addUser.jelly24
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/advanced.jelly40
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/ajax.jelly48
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/ajaxBuildHistory.jelly27
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/ajaxBuildQueue.jelly26
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/ajaxExecutors.jelly26
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/ajaxMatrix.jelly40
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/ajaxRows.jelly36
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/all.jelly27
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/artifactList.jelly83
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/artifacts-index.jelly35
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/askRootPassword.jelly56
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/atom.jelly55
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/available.jelly24
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/badge.jelly26
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/ballColorTd.jelly34
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/bar.jelly65
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/block.jelly28
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/body.jelly121
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/booleanRadio.jelly39
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/build-permalink.jelly35
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/buildCaption.jelly43
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/buildHealth.jelly67
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/buildLink.jelly49
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/buildListTable.jelly68
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/buildProgressBar.jelly33
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/buildRangeLink.jelly43
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/buildStatusSummary.jelly29
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/buildTimeTrend.jelly75
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/builds.jelly38
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/cascadingDescriptorList.jelly56
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/cause.jelly21
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/causeOfDeath.jelly51
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/cc.xml.jelly41
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/changes.jelly39
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/checkUpdates.jelly43
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/checkbox.jelly61
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/column.jelly22
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/columnHeader.jelly21
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/combobox.jelly47
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config-blockWhenDownstreamBuilding.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config-blockWhenUpstreamBuilding.jelly31
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config-buildWrappers.jelly24
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config-builders.jelly36
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config-cleanWorkspace.jelly28
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config-customWorkspace.jelly31
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config-disableBuild.jelly25
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config-publishers.jelly24
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config-quietPeriod.jelly33
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config-retryCount.jelly32
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config-scm.jelly37
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config-trigger.jelly33
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config-upstream-pseudo-trigger.jelly37
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/config.jelly20
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/configure-advanced.jelly24
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/configure-common.jelly98
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/configure-entries.jelly84
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/configure.jelly53
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/configureExecutors.jelly41
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/confirm.jelly47
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/confirmDelete.jelly36
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/console.jelly67
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/consoleFull.jelly21
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/control.jelly162
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/custom-jnlp.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/delete.jelly35
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/deleteConfirmationPanel.jelly24
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/description.jelly34
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/descriptionForm.jelly34
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/descriptorList.jelly79
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/descriptorRadioList.jelly56
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/detail.jelly20
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/digest.jelly21
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/dir.jelly97
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/disconnect.jelly32
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/downgrade.jelly28
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/dropdownDescriptorSelector.jelly53
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/dropdownList.jelly74
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/dropdownListBlock.jelly51
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/editDescription.jelly32
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/editTypeIcon.jelly25
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/editableComboBox.jelly54
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/editableComboBoxValue.jelly26
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/editableDescription.jelly49
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/entries.jelly28
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/entry.jelly90
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/enum.jelly36
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/enumSet.jelly35
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/error.jelly52
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/executors.jelly163
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/expandButton.jelly35
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/expandableTextbox.jelly75
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/feeds.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/fingerprintCheck.jelly45
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/firstUser.jelly24
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/floatingBox.jelly47
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/foo.jelly19
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/footer.jelly34
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/form.jelly90
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/global.jelly31
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/hasPermission.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/header.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/help-launcher.jelly34
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/help.jelly24
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/helpArea.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/hetero-list.jelly127
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/hetero-radio.jelly49
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/iconSize.jelly45
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/inProgress.jelly31
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/index.jelly73
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/installed.jelly157
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/invisibleEntry.jelly28
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/isAdmin.jelly23
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/isAdminOrTest.jelly34
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/jobDeleteForm.jelly80
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/jobLink.jelly29
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/jobpropertysummaries.jelly25
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/label.jelly27
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/layout.jelly303
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/legend.jelly80
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/levels.jelly68
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/link.jelly31
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/list.jelly52
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/listScmBrowsers.jelly37
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/load-statistics.jelly26
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/log.jelly32
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/logKeep.jelly33
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/login.jelly66
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/loginDialog.jelly80
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/loginError.jelly51
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/loginLink.jelly116
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/main-panel.jelly28
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/main.jelly69
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/manage.jelly131
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/markOffline.jelly37
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/matrix.jelly97
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/message.jelly24
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/myViewTabs.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/nested.jelly34
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/new.jelly35
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/newInstanceDetail.jelly21
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/newJob.jelly32
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/newJobDetail.jelly21
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/newView.jelly19
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/newViewDetail.jelly21
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/noJob.jelly36
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/noPrincipal.jelly29
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/noWorkspace.jelly53
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/node.jelly32
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/nodepropertysummaries.jelly28
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/opensearch.xml.jelly34
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/option.jelly36
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/optionalBlock.jelly88
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/optionalProperty.jelly39
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/outline.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/pane.jelly44
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/password.jelly55
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/permalinks.jelly28
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/prepareDatabinding.jelly31
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/progressBar.jelly43
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/progressiveText.jelly87
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/project-changes.jelly70
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/projectActionFloatingBox.jelly34
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/projectRelationship-help.jelly42
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/projectRelationship.jelly88
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/projectView.jelly77
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/projectViewNested.jelly49
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/projectViewRow.jelly37
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/property.jelly35
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/propertyTable.jelly44
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/queue.jelly98
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/radio.jelly25
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/radioBlock.jelly72
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/readOnlyTextbox.jelly67
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/rename.jelly50
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/repeatable.jelly148
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/repeatableDeleteButton.jelly28
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/repeatableProperty.jelly71
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/richtextarea.jelly34
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/rightspace.jelly27
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/row.jelly27
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/rowSet.jelly49
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/rss20.jelly44
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/rssBar-with-iconSize.jelly22
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/rssBar.jelly32
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/rssHeader.jelly24
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/scriptConsole.jelly50
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/search-failed.jelly47
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/searchPopup.jelly51
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/section.jelly52
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/select.jelly51
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/setIconSize.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/side-panel.jelly23
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/sidepanel.jelly46
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/sidepanel2.jelly27
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/signup.jelly24
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/signupWithFederatedIdentity.jelly45
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/sites.jelly61
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/slave-agent.jnlp.jelly84
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/slave-mode.jelly34
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/status.jelly21
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/submit.jelly34
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/success.jelly31
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/summary.jelly54
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/svn-password.jelly46
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/systemInfo.jelly42
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/tab.jelly57
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/tabBar.jelly37
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/table.jelly139
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/task.jelly93
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/taskWithDialog.jelly112
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/tasks.jelly33
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/test-result.jelly40
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/test1.xml17
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/textarea.jelly60
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/textbox.jelly73
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/threadDump.jelly38
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/upstream-downstream.jelly52
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/validateButton.jelly58
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/value.jelly26
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/viewTabs.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/whoAmI.jelly67
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/wipeOutWorkspace.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/wipeOutWorkspaceBlocked.jelly30
-rw-r--r--xpath-service/src/test/resources/org/hudsonci/xpath/yui.jelly30
261 files changed, 14399 insertions, 0 deletions
diff --git a/xpath-service/.gitignore b/xpath-service/.gitignore
new file mode 100644
index 0000000..a6f89c2
--- /dev/null
+++ b/xpath-service/.gitignore
@@ -0,0 +1 @@
+/target/ \ No newline at end of file
diff --git a/xpath-service/README.md b/xpath-service/README.md
new file mode 100644
index 0000000..64bf773
--- /dev/null
+++ b/xpath-service/README.md
@@ -0,0 +1,15 @@
+xpath-service
+=============
+
+Provides XPath and Stylesheet features for Hudson and Jelly (which no longer
+contain Jaxen).
+
+Converting dom4j XPath-related calls to XPath service is usually trivial, e.g.,
+
+ doc.selectNodes(pathExpr)
+
+becomes
+
+ new XPath(pathExpr).selectNodes(doc)
+
+
diff --git a/xpath-service/pom.xml b/xpath-service/pom.xml
new file mode 100644
index 0000000..cda5a39
--- /dev/null
+++ b/xpath-service/pom.xml
@@ -0,0 +1,78 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.hudsonci.xpath</groupId>
+ <artifactId>xpath-service</artifactId>
+ <packaging>jar</packaging>
+ <version>1.0.3-SNAPSHOT</version>
+ <name>xpath-service</name>
+ <url>http://hudson-ci.org/</url>
+ <description>XPath Service for Jelly</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jvnet.hudson.dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ <version>1.6.1-hudson-3</version>
+ <optional>true</optional>
+ </dependency>
+ </dependencies>
+
+ <developers>
+ <developer>
+ <name>Bob Foster</name>
+ <id>bobfoster</id>
+ <email>bobfoster@gmail.com</email>
+ </developer>
+ </developers>
+
+ <licenses>
+ <license>
+ <name>Eclipse Public License v1.0</name>
+ <url>http://www.eclipse.org/legal/epl-v10.html</url>
+ <comments>All source code is made available under the terms of the Eclipse Public License 1.0</comments>
+ </license>
+ </licenses>
+
+ <distributionManagement>
+ <snapshotRepository>
+ <id>sonatype-nexus-snapshots</id>
+ <name>Sonatype Nexus Snapshots</name>
+ <url>${sonatypeOssDistMgmtSnapshotsUrl}</url>
+ </snapshotRepository>
+ <repository>
+ <id>sonatype-nexus-staging</id>
+ <name>Nexus Staging Repository</name>
+ <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+ </repository>
+ </distributionManagement>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <version>2.1</version>
+ <configuration>
+ <!-- enable release profile during the release, create IPS package, and sign bits. -->
+ <prepareVerifyArgs>-P release,sign</prepareVerifyArgs>
+ <goals>-DskipTests javadoc:javadoc deploy javadoc:aggregate</goals>
+ <pushChanges>false</pushChanges>
+ <localCheckout>true</localCheckout>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <scm>
+ <connection>scm:git:git://github.com/hudson3-plugins/${project.artifactId}.git</connection>
+ <developerConnection>scm:git:git@github.com:hudson3-plugins/${project.artifactId}.git</developerConnection>
+ <url>https://github.com/hudson3-plugins/${project.artifactId}</url>
+ </scm>
+
+</project>
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/Stylesheet.java b/xpath-service/src/main/java/org/hudsonci/xpath/Stylesheet.java
new file mode 100644
index 0000000..5e6f29e
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/Stylesheet.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath;
+
+import java.util.ServiceLoader;
+import org.dom4j.rule.Action;
+import org.dom4j.rule.Rule;
+import org.hudsonci.xpath.impl.StylesheetJavaImpl;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public class Stylesheet implements StylesheetAPI {
+
+ StylesheetAPI impl;
+
+ private static StylesheetAPIFactory factory = null;
+
+ public static void provideStylesheetService(StylesheetAPIFactory factory) {
+ Stylesheet.factory = factory;
+ }
+
+ public Stylesheet() {
+ if (factory != null)
+ impl = factory.newStylesheetAPI();
+
+ // If no service provider (yet) use the default implementation.
+ // NB: the default implementation does NOT work.
+
+ if (impl == null)
+ impl = new StylesheetJavaImpl();
+ }
+
+ public void applyTemplates(Object source, XPath select, String mode) throws Exception {
+ impl.applyTemplates(source, select, mode);
+ }
+
+ public void applyTemplates(Object source, String mode) throws Exception {
+ impl.applyTemplates(source, mode);
+ }
+
+ public void setValueOfAction(Action valueOfAction) {
+ impl.setValueOfAction(valueOfAction);
+ }
+
+ public void run(Object input) throws Exception {
+ impl.run(input);
+ }
+
+ public void addRule(Rule rule) {
+ impl.addRule(rule);
+ }
+
+ public void setModeName(String modeName) {
+ impl.setModeName(modeName);
+ }
+
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/StylesheetAPI.java b/xpath-service/src/main/java/org/hudsonci/xpath/StylesheetAPI.java
new file mode 100644
index 0000000..41234ce
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/StylesheetAPI.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath;
+
+import org.dom4j.rule.Action;
+import org.dom4j.rule.Rule;
+import org.hudsonci.xpath.XPath;
+
+/**
+ *
+ * @author bobfoster
+ */
+public interface StylesheetAPI {
+
+ public void applyTemplates(Object source, XPath select, String mode) throws Exception;
+
+ public void applyTemplates(Object source, String mode) throws Exception;
+
+ public void setValueOfAction(Action valueOfAction);
+
+ public void run(Object input) throws Exception;
+
+ public void addRule(Rule rule);
+
+ public void setModeName(String modeName);
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/StylesheetAPIFactory.java b/xpath-service/src/main/java/org/hudsonci/xpath/StylesheetAPIFactory.java
new file mode 100644
index 0000000..06eb3f7
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/StylesheetAPIFactory.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public interface StylesheetAPIFactory {
+ public StylesheetAPI newStylesheetAPI();
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/XNamespaceContext.java b/xpath-service/src/main/java/org/hudsonci/xpath/XNamespaceContext.java
new file mode 100644
index 0000000..350712a
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/XNamespaceContext.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath;
+
+import java.util.*;
+import javax.xml.namespace.NamespaceContext;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public class XNamespaceContext implements NamespaceContext {
+
+ Map map;
+ PrefixMap prefixMap;
+
+ private static class PrefixMap {
+ Map<String,List<String>> map = new HashMap<String,List<String>>();
+
+ PrefixMap(Map nsMap) {
+ for (Object obj : nsMap.entrySet()) {
+ Map.Entry entry = (Map.Entry) obj;
+ String prefix = (String) entry.getKey();
+ String ns = (String) entry.getValue();
+ List<String> list = map.get(ns);
+ if (list == null) {
+ list = new ArrayList<String>();
+ map.put(ns, list);
+ }
+ list.add(prefix);
+ }
+ }
+
+ List<String> getPrefixes(String ns) {
+ List<String> list = map.get(ns);
+ if (list == null)
+ return Collections.EMPTY_LIST;
+ return list;
+ }
+
+ }
+
+ public XNamespaceContext(Map uris) {
+ this.map = uris;
+ }
+
+ public String getNamespaceURI(String prefix) {
+ return (String) map.get(prefix);
+ }
+
+ private PrefixMap getPrefixMap() {
+ if (prefixMap == null)
+ prefixMap = new PrefixMap(map);
+ return prefixMap;
+ }
+
+ public String getPrefix(String namespaceURI) {
+ List<String> list = getPrefixMap().getPrefixes(namespaceURI);
+ if (list.size() > 0)
+ return list.get(0);
+ return null;
+ }
+
+ public Iterator getPrefixes(String namespaceURI) {
+ return getPrefixMap().getPrefixes(namespaceURI).iterator();
+ }
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/XPath.java b/xpath-service/src/main/java/org/hudsonci/xpath/XPath.java
new file mode 100644
index 0000000..99ab6e0
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/XPath.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath;
+
+import java.util.List;
+import java.util.ServiceLoader;
+import org.dom4j.Node;
+import org.hudsonci.xpath.impl.XPathJavaImpl;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public class XPath implements XPathAPI {
+
+ XPathAPI impl;
+
+ private static XPathAPIFactory factory = null;
+
+ public static void provideXPathService(XPathAPIFactory factory) {
+ XPath.factory = factory;
+ }
+
+ public XPath(String expr) throws XPathException {
+
+ if (factory != null)
+ impl = factory.newXPathAPI(expr);
+
+ // If no service provider, fall back on default implementation
+ // NB: If the default implementation was robust, we wouldn't
+ // need the service!
+ if (impl == null)
+ impl = new XPathJavaImpl(expr);
+ }
+
+ public void setVariableContext(XVariableContext varContext) {
+ impl.setVariableContext(varContext);
+ }
+
+ public XVariableContext getVariableContext() {
+ return impl.getVariableContext();
+ }
+
+ public void setNamespaceContext(XNamespaceContext nsContext) {
+ impl.setNamespaceContext(nsContext);
+ }
+
+ public XNamespaceContext getNamespaceContext() {
+ return impl.getNamespaceContext();
+ }
+
+ public Object evaluate(Object xpathContext) throws XPathException {
+ return impl.evaluate(xpathContext);
+ }
+
+ public boolean booleanValueOf(Object xpathContext) throws XPathException {
+ return impl.booleanValueOf(xpathContext);
+ }
+
+ public double numberValueOf(Object xpathContext) throws XPathException {
+ return impl.numberValueOf(xpathContext);
+ }
+
+ public String stringValueOf(Object xpathContext) throws XPathException {
+ return impl.stringValueOf(xpathContext);
+ }
+
+ public Node selectSingleNode(Object xpathContext) throws XPathException {
+ return impl.selectSingleNode(xpathContext);
+ }
+
+ public List selectNodes(Object xpathContext) throws XPathException {
+ return impl.selectNodes(xpathContext);
+ }
+
+ public String toString() {
+ return impl.toString();
+ }
+
+ public Object getImpl() {
+ return impl;
+ }
+
+ public void setExpr(String expr) {
+ impl.setExpr(expr);
+ }
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/XPathAPI.java b/xpath-service/src/main/java/org/hudsonci/xpath/XPathAPI.java
new file mode 100644
index 0000000..e0cd7d1
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/XPathAPI.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath;
+
+import org.hudsonci.xpath.XNamespaceContext;
+import org.hudsonci.xpath.XVariableContext;
+import java.util.List;
+import org.dom4j.Node;
+import org.hudsonci.xpath.XPathException;
+
+/**
+ *
+ * @author bobfoster
+ */
+public interface XPathAPI {
+
+ public void setVariableContext(XVariableContext varContext);
+
+ public XVariableContext getVariableContext();
+
+ public void setNamespaceContext(XNamespaceContext nsContext);
+
+ public XNamespaceContext getNamespaceContext();
+
+ public Object evaluate(Object xpathContext) throws XPathException;
+
+ public boolean booleanValueOf(Object xpathContext) throws XPathException;
+
+ public double numberValueOf(Object xpathContext) throws XPathException;
+
+ public String stringValueOf(Object xpathContext) throws XPathException;
+
+ public Node selectSingleNode(Object xpathContext) throws XPathException;
+
+ public List selectNodes(Object xpathContext) throws XPathException;
+
+ public String toString();
+
+ public void setExpr(String expr);
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/XPathAPIFactory.java b/xpath-service/src/main/java/org/hudsonci/xpath/XPathAPIFactory.java
new file mode 100644
index 0000000..fe29123
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/XPathAPIFactory.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public interface XPathAPIFactory {
+ XPathAPI newXPathAPI(String expr);
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/XPathException.java b/xpath-service/src/main/java/org/hudsonci/xpath/XPathException.java
new file mode 100644
index 0000000..b61aa2a
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/XPathException.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public class XPathException extends Exception {
+
+ public XPathException(String msg) {
+ super(msg);
+ }
+
+ public XPathException(Throwable t) {
+ super(t);
+ }
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/XVariableContext.java b/xpath-service/src/main/java/org/hudsonci/xpath/XVariableContext.java
new file mode 100644
index 0000000..f455c99
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/XVariableContext.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath;
+
+import javax.xml.xpath.XPathException;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public interface XVariableContext {
+
+ Object getVariableValue(String namespaceURI, String prefix, String localName) throws Exception;
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/impl/Dom2Dom.java b/xpath-service/src/main/java/org/hudsonci/xpath/impl/Dom2Dom.java
new file mode 100644
index 0000000..8835b3f
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/impl/Dom2Dom.java
@@ -0,0 +1,342 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.WeakHashMap;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.dom4j.*;
+import org.hudsonci.xpath.XPathException;
+import org.w3c.dom.NodeList;
+
+/**
+ * Dom2Dom translates a dom4j document to a W3C document and keeps
+ * a map of dom4j nodes translated to W3C nodes.
+ *
+ * @author Bob Foster
+ */
+public class Dom2Dom {
+
+ private static Map<Document,DocMapPair> cache
+ = new WeakHashMap<Document,DocMapPair>();
+
+ private ReverseMap reverseMap;
+ private org.w3c.dom.Document wdoc;
+ private boolean trimText;
+ private org.w3c.dom.Element currentElement;
+ private Text lastText;
+
+ /* These classes for much-needed brevity */
+ private static class ReverseMap extends HashMap<org.w3c.dom.Node,Node> {}
+ private static class DocMapPair extends Pair<org.w3c.dom.Document,ReverseMap> {
+ public DocMapPair(org.w3c.dom.Document doc,ReverseMap map) {
+ super(doc, map);
+ }
+ }
+
+ private String getLocalName(String qualifiedName) {
+ // different representation in w3c
+ String localName = null;
+ int colon = qualifiedName.indexOf(':');
+ if (colon >= 0)
+ localName = qualifiedName.substring(colon+1);
+ return localName;
+ }
+
+ private String getNamespaceURI(String namespaceURI) {
+ // different representation in w3c
+ if ("".equals(namespaceURI))
+ return null;
+ return namespaceURI;
+ }
+
+ private class Name {
+ String namespaceURI;
+ String qualifiedName;
+ Name(Node n) {
+ qualifiedName = n.getName();
+ }
+ Name(Element el) {
+ qualifiedName = el.getQualifiedName();
+ namespaceURI = getNamespaceURI(el.getNamespaceURI());
+ }
+ Name(Attribute el) {
+ // thank dom4j for this code duplication
+ qualifiedName = el.getQualifiedName();
+ namespaceURI = getNamespaceURI(el.getNamespaceURI());
+ }
+ Name(Namespace ns) {
+ String prefix = ns.getPrefix();
+ qualifiedName = "xmlns" + ("".equals(prefix) ? "" : ":"+prefix);
+ }
+ }
+
+ /**
+ * Get original dom4j Node. Valid if dom2dom returned successfully.
+ *
+ * @see #dom2Dom(org.dom4j.Node, boolean)
+ *
+ * @param node W3C DOM Node
+ * @return the dom4j node that was mapped by dom2dom to the argument node
+ */
+ public Node getOriginalNode(org.w3c.dom.Node node) {
+ Node d4jNode = reverseMap.get(node);
+ if (d4jNode == null) {
+ // Xerces is playing tricks, allocating nodes on the fly.
+ SimplePath path = getPathForNode(node, null);
+ Document doc = getDom4jDocument(node);
+ d4jNode = getNodeForPath(doc, path);
+ }
+ return d4jNode;
+ }
+
+ private Document getDom4jDocument(org.w3c.dom.Node node) {
+ org.w3c.dom.Document doc = node.getOwnerDocument();
+ Document document = (Document) reverseMap.get(doc);
+ if (document == null)
+ throw new IllegalStateException("Document not found in reverse map");
+ return document;
+ }
+
+ private static class SimplePath {
+ int childNum;
+ SimplePath next;
+ SimplePath(int childNum, SimplePath next) {
+ this.childNum = childNum;
+ this.next = next;
+ }
+ }
+
+ private SimplePath getPathForNode(org.w3c.dom.Node node, SimplePath next) {
+ if (node instanceof org.w3c.dom.Document)
+ return next;
+ org.w3c.dom.Node parent = node.getParentNode();
+ int i = 0;
+ for (org.w3c.dom.Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child.equals(node))
+ return getPathForNode(parent, new SimplePath(i, next));
+ i++;
+ }
+ throw new IllegalStateException("Node not a child of its parent");
+ }
+
+ private Node getNodeForPath(Document doc, SimplePath path) {
+ Node node = doc;
+ for (SimplePath p = path; p != null; p = p.next) {
+ if (!(node instanceof Branch))
+ throw new IllegalStateException("Node with children not a Branch");
+ Branch parent = (Branch) node;
+ node = parent.node(p.childNum);
+ }
+ return node;
+ }
+
+ /**
+ * Map a org.dom4j.Node to a org.w3c.dom.Node, including its ancestors
+ * and descendents.
+ *
+ * Once mapped, originalNode will return the original Node
+ * corresponding to any mapped w3c Node.
+ *
+ * @see #getOriginalNode(org.w3c.dom.Node)
+ *
+ * @param node to convert
+ * @param trim true if whitespace is to be trimmed from any consecutive
+ * sequence of Text nodes; false if whitespace retained
+ * @return W3C DOM Node corresponding to node argument
+ * @throws XPathException
+ */
+ public org.w3c.dom.Node dom2DomX(Node node, boolean trim) throws XPathException {
+
+ trimText = trim;
+
+ // The first time we see a context node we create a w3c Document
+ // for XPath processing. The important thing is that equals
+ // works correctly.
+
+ Document ddoc = node.getDocument();
+
+ reverseMap = new ReverseMap();
+
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder;
+ try {
+ builder = factory.newDocumentBuilder();
+ } catch (ParserConfigurationException ex) {
+ throw new XPathException(ex);
+ }
+ wdoc = builder.newDocument();
+
+ createChildren(ddoc, wdoc);
+
+ return findNode(wdoc, node);
+ }
+
+ public org.w3c.dom.Node dom2Dom(Node node, boolean trim) throws XPathException {
+
+ trimText = trim;
+
+ // The first time we see a context node we create a w3c Document
+ // for XPath processing. The important thing is that equals
+ // works correctly.
+
+ // This cache is probably bogus because Xerces likes to create Nodes
+ // as flyweight objects on the fly. So different operations might
+ // retrieve the same actual Node in two different NodeImpl objects
+ // that do not compare equals.
+ //
+ // It did seem to work for some simple tests and when it does work
+ // it is fast, but I've worked around it in getOriginalNode.
+
+ Document ddoc = node.getDocument();
+ DocMapPair pair = cache.get(ddoc);
+
+ if (pair == null) {
+
+ ReverseMap map = new ReverseMap();
+
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder;
+ try {
+ builder = factory.newDocumentBuilder();
+ } catch (ParserConfigurationException ex) {
+ throw new XPathException(ex);
+ }
+ org.w3c.dom.Document doc = builder.newDocument();
+
+ map.put(doc, ddoc);
+ pair = new DocMapPair(doc, map);
+
+ cache.put(ddoc, pair);
+ }
+
+ wdoc = pair.getLeft();
+ reverseMap = pair.getRight();
+
+ if (!wdoc.hasChildNodes())
+ createChildren(ddoc, wdoc);
+
+ return findNode(wdoc, node);
+ }
+
+ private org.w3c.dom.Node findNode(org.w3c.dom.Node ancestor, Node node) {
+ Node ancestorNode = reverseMap.get(ancestor);
+ if (ancestorNode == node)
+ return ancestor;
+ NodeList list = ancestor.getChildNodes();
+ for (int i = 0, n = list.getLength(); i < n; i++) {
+ org.w3c.dom.Node child = (org.w3c.dom.Node) list.item(i);
+ org.w3c.dom.Node found = findNode(child, node);
+ if (found != null)
+ return found;
+ }
+ return null;
+ }
+
+ private void createChildren(Branch dparent, org.w3c.dom.Node wparent) {
+ Branch b = (Branch) dparent;
+ for (int i = 0, n = b.nodeCount(); i < n; i++) {
+ Node child = b.node(i);
+ org.w3c.dom.Node wchild = createChild(child, wparent);
+ if (wchild != null)
+ createChildren((Branch)child, wchild);
+ }
+ endText(wparent);
+ }
+
+ StringBuilder textBuilder = new StringBuilder();
+
+ private void endText(org.w3c.dom.Node wparent) {
+ if (textBuilder.length() > 0) {
+ String text = trimText ? textBuilder.toString().trim() : textBuilder.toString();
+ org.w3c.dom.Text textNode = wdoc.createTextNode(text);
+ wparent.appendChild(textNode);
+ textBuilder.setLength(0);
+ reverseMap.put(textNode, lastText);
+ }
+ }
+
+ private org.w3c.dom.Node createChild(Node child, org.w3c.dom.Node wparent) {
+ int type = child.getNodeType();
+
+ // Collapse multiple consecutive text nodes to a single text node
+ // with trimmed value.
+ if (type != Node.TEXT_NODE)
+ endText(wparent);
+
+ Name name;
+ org.w3c.dom.Node node = null;
+
+ switch (type) {
+ case Node.ATTRIBUTE_NODE:
+ break;
+ case Node.CDATA_SECTION_NODE:
+ CDATA cd = (CDATA) child;
+ wparent.appendChild(node = wdoc.createCDATASection(cd.getText()));
+ break;
+ case Node.COMMENT_NODE:
+ Comment co = (Comment) child;
+ wparent.appendChild(node = wdoc.createComment(co.getText()));
+ break;
+ case Node.DOCUMENT_TYPE_NODE:
+ DocumentType dt = (DocumentType) child;
+ wparent.appendChild(new XDocumentType(dt, wparent));
+ break;
+ case Node.ELEMENT_NODE:
+ Element el = (Element) child;
+ name = new Name(el);
+ org.w3c.dom.Element e = name.namespaceURI == null
+ ? wdoc.createElement(name.qualifiedName)
+ : wdoc.createElementNS(name.namespaceURI, name.qualifiedName);
+ wparent.appendChild(e);
+ node = currentElement = e;
+
+ for (int i = 0, n = el.attributeCount(); i < n; i++) {
+ Attribute at = el.attribute(i);
+ name = new Name(at);
+ if (name.namespaceURI == null)
+ e.setAttribute(name.qualifiedName, at.getValue());
+ else
+ e.setAttributeNS(name.namespaceURI, name.qualifiedName, at.getValue());
+ }
+ return e;
+ case Node.ENTITY_REFERENCE_NODE:
+ break;
+ case Node.PROCESSING_INSTRUCTION_NODE:
+ ProcessingInstruction p = (ProcessingInstruction) child;
+ wparent.appendChild(node = wdoc.createProcessingInstruction(p.getTarget(), p.getText()));
+ break;
+ case Node.TEXT_NODE:
+ textBuilder.append(child.getText());
+ lastText = (Text) child;
+ break;
+ case Node.NAMESPACE_NODE:
+ Namespace ns = (Namespace) child;
+ name = new Name(ns);
+ currentElement.setAttribute(name.qualifiedName, ns.getURI());
+ break;
+ default:
+ throw new IllegalStateException("Unknown node type");
+ }
+ if (node != null)
+ reverseMap.put(node, child);
+ return null;
+ }
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/impl/Pair.java b/xpath-service/src/main/java/org/hudsonci/xpath/impl/Pair.java
new file mode 100644
index 0000000..9bbf78b
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/impl/Pair.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath.impl;
+
+/**
+ * YAPC
+ *
+ * @author Bob Foster
+ */
+public class Pair<L,R> {
+
+ private L left;
+ private R right;
+
+ public Pair(L left, R right) {
+ this.left = left;
+ this.right = right;
+ }
+
+ public L getLeft() {
+ return left;
+ }
+
+ public R getRight() {
+ return right;
+ }
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/impl/Rewriter.java b/xpath-service/src/main/java/org/hudsonci/xpath/impl/Rewriter.java
new file mode 100644
index 0000000..94db853
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/impl/Rewriter.java
@@ -0,0 +1,279 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.dom4j.Branch;
+import org.dom4j.Document;
+import org.dom4j.Node;
+import org.hudsonci.xpath.XNamespaceContext;
+import org.hudsonci.xpath.XPathException;
+import org.hudsonci.xpath.XVariableContext;
+
+/**
+ * Rewrite an XPath expression containing Node variables.
+ *
+ * @author Bob Foster
+ */
+public class Rewriter {
+
+ XVariableContext varContext;
+ XNamespaceContext nsContext;
+
+ /**
+ * Expr represents a sub-expression of an XPath expression.
+ * There are only two sub-types, Var and Str, representing
+ * an XPath variable and anything else, respectively.
+ */
+ private abstract class Expr {
+ Expr next;
+ Expr() {
+ }
+ void collectNodes(List<Node> list) throws XPathException {
+ if (next != null)
+ next.collectNodes(list);
+ }
+ void replaceNodes(Node dominant) {
+ if (next != null)
+ next.replaceNodes(dominant);
+ }
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ collectString(sb);
+ return sb.toString();
+ }
+ abstract void collectString(StringBuilder sb);
+ }
+
+ /**
+ * XPath variable.
+ */
+ private class Var extends Expr {
+ String var;
+ Object value;
+ String replacement;
+ Var(String var) {
+ this.var = var;
+ }
+ void collectNodes(List<Node> list) throws XPathException {
+ String ns = "";
+ String px = "";
+ String ln = var;
+ if (nsContext != null) {
+ int colon = var.indexOf(':');
+ if (colon >= 0) {
+ px = var.substring(0, colon);
+ ln = var.substring(colon+1);
+ ns = nsContext.getNamespaceURI(px);
+ }
+ }
+ try {
+ value = varContext.getVariableValue(ns, px, ln);
+ if (value instanceof Node)
+ list.add((Node) value);
+ if (next != null)
+ next.collectNodes(list);
+ } catch (Exception e) {
+ throw new XPathException(e);
+ }
+ }
+ void collectString(StringBuilder sb) {
+ sb.append(replacement);
+ if (next != null)
+ next.collectString(sb);
+ }
+ void replaceNodes(Node dominant) {
+ if (value == dominant)
+ replacement = ".";
+ else
+ // For non-dominant nodes, the reasoning is the $var will work
+ // ok, as the dominant node establishes the context of evaluation.
+ replacement = "$"+var;
+ if (next != null)
+ next.replaceNodes(dominant);
+ }
+ }
+
+ /**
+ * Anything but an XPath variable.
+ */
+ private class Str extends Expr {
+ String str;
+ Str(String str) {
+ this.str = str;
+ }
+ void collectString(StringBuilder sb) {
+ sb.append(str);
+ if (next != null)
+ next.collectString(sb);
+ }
+ }
+
+ Expr first;
+ Expr last;
+
+ void addExpr(Expr e) {
+ if (first == null)
+ first = last = e;
+ else {
+ last.next = e;
+ last = e;
+ }
+ }
+
+ /** Characters in an XPath expression that can't be part of a variable name. */
+ static boolean[] nonVar = new boolean[255];
+ static {
+ nonVar[' '] = nonVar['\t'] = nonVar['\n'] = nonVar['\r'] = true;
+ nonVar['('] = nonVar[')'] = nonVar['['] = nonVar[']'] = true;
+ nonVar['+'] = nonVar['-'] = nonVar['*'] = nonVar['|'] = true;
+ nonVar['='] = nonVar['!'] = nonVar['>'] = nonVar['<'] = true;
+ nonVar['/'] = nonVar['$'] = nonVar['?'] = true;
+ nonVar['.'] = nonVar[','] = true;
+ }
+
+ /**
+ * @param c
+ * @return true if c is not a valid variable character (a much simpler
+ * question to answer than if c <i>is</i> a valid character)
+ */
+ private boolean endOfVar(char c) {
+ return c > 255 || nonVar[c];
+ }
+
+ /**
+ * Find the dominant node in a list of more than one Node.
+ * @param nodes list with more than one node
+ * @return the dominant node (node that contains the others)
+ * @throws Exception
+ */
+ private Node findDominantNode(List<Node> nodes) throws XPathException {
+ Node dominant = null;
+ for (Node node : nodes) {
+ if (dominant == null)
+ dominant = node;
+ else
+ dominant = findDominantNode(dominant, node);
+ }
+ if (dominant == null) throw new XPathException("No dominant node found in expression");
+ return dominant;
+ }
+
+ /**
+ * @param node1
+ * @param node2
+ * @return the node that is or contains the other
+ * @throws Exception
+ */
+ private Node findDominantNode(Node node1, Node node2) {
+ // Fast tests
+ if (node1 == node2)
+ return node1;
+ // Both nodes come from same document
+ Document doc = node1.getDocument();
+ if (node1 == doc)
+ return node1;
+ if (node2 == doc)
+ return node2;
+ // Slow tests
+ if (nodeContains(node1, node2))
+ return node1;
+ if (nodeContains(node2, node1))
+ return node2;
+ return null;
+ }
+
+ private boolean nodeContains(Node parent, Node node) {
+ if (parent == node)
+ return true;
+ if (parent instanceof Branch) {
+ Branch branch = (Branch) parent;
+ List children = branch.content();
+ for (int i = 0, n = children.size(); i < n; i++) {
+ boolean contains = nodeContains((Node)children.get(i), node);
+ if (contains)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Rewrite the XPath expression such that at least one Node-valued
+ * variable is replaced by the outer-most context ".".
+ *
+ * Should only be called if the XPath evaluation context is null.
+ *
+ * @param expr XPath expression
+ * @param varContext context for variables
+ * @param nsContext context for namespaces
+ * @return Pair<rewritten-expression, context-node>
+ * @throws XPathException if no Node-valued variable that is a suitable
+ * context is found
+ */
+ public Pair<String,Node> rewriteExpression(String expr, XVariableContext varContext, XNamespaceContext nsContext) throws XPathException {
+ this.varContext = varContext;
+ this.nsContext = nsContext;
+
+ String rewrittenExpression = expr;
+ Node dominantNode = null;
+
+ // Split into subexpressions
+ first = null;
+ last = null;
+ int start = 0;
+ for (int i = 0, n = expr.length(); i < n; i++) {
+ char c = expr.charAt(i);
+ if (c == '$') {
+ if (i > start)
+ addExpr(new Str(expr.substring(start, i)));
+ // start of variable
+ int j = start = i + 1;
+ for (; j < n; j++) {
+ char v = expr.charAt(j);
+ if (endOfVar(v))
+ break;
+ }
+ addExpr(new Var(expr.substring(start, j)));
+ start = j;
+ i = j - 1;
+ }
+ }
+ if (start < expr.length())
+ addExpr(new Str(expr.substring(start)));
+
+ List<Node> nodes = new ArrayList<Node>();
+ first.collectNodes(nodes);
+
+ if (nodes.size() > 0) {
+ dominantNode = nodes.get(0);
+
+ if (nodes.size() > 1)
+ dominantNode = findDominantNode(nodes);
+
+ first.replaceNodes(dominantNode);
+
+ rewrittenExpression = first.toString();
+ }
+
+ if (rewrittenExpression == null)
+ throw new XPathException("Cannot rewrite expression to obtain a valid context node");
+
+ return new Pair(rewrittenExpression, dominantNode);
+ }
+
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/impl/StylesheetJavaImpl.java b/xpath-service/src/main/java/org/hudsonci/xpath/impl/StylesheetJavaImpl.java
new file mode 100644
index 0000000..7dad16f
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/impl/StylesheetJavaImpl.java
@@ -0,0 +1,47 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.hudsonci.xpath.impl;
+
+import org.hudsonci.xpath.StylesheetAPI;
+import org.dom4j.rule.Action;
+import org.dom4j.rule.Rule;
+import org.hudsonci.xpath.XPath;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public class StylesheetJavaImpl implements StylesheetAPI {
+
+ public StylesheetJavaImpl() {
+
+ }
+
+ public void applyTemplates(Object source, XPath select, String mode) throws Exception {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void applyTemplates(Object source, String mode) throws Exception {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void setValueOfAction(Action valueOfAction) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void run(Object input) throws Exception {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void addRule(Rule rule) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void setModeName(String modeName) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/impl/Trim.java b/xpath-service/src/main/java/org/hudsonci/xpath/impl/Trim.java
new file mode 100644
index 0000000..3922ed7
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/impl/Trim.java
@@ -0,0 +1,96 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.hudsonci.xpath.impl;
+
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+import org.dom4j.Branch;
+import org.dom4j.Node;
+import org.dom4j.Text;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public class Trim {
+
+ private static Map<Node,Node> trimmed = new WeakHashMap<Node,Node>();
+
+
+ public static Node trimNode(Node node) {
+ if (node instanceof Branch)
+ trimBranch((Branch) node);
+ return node;
+ }
+
+ public static void trimBranch(Branch branch) {
+ // This does not normalize whitespace!
+ // The document tree is modified in place, but no nodes are removed.
+ if (trimmed.get(branch) != null) return;
+ trimmed.put(branch, branch);
+ List content = branch.content();
+ // trim leading whitespace
+ // NB: dom4j can have multiple consecutive Text nodes
+ boolean first = true;
+ for (int i = 0, n = content.size(); i < n; i++) {
+ Object obj = content.get(i);
+ if (obj instanceof Text) {
+ Text text = (Text) obj;
+ if (first) {
+ String s = trimLeading(text.getText());
+ text.setText(s);
+ if (s.length() > 0)
+ first = false;
+ }
+ } else {
+ first = false;
+ if (obj instanceof Branch)
+ trimBranch((Branch) obj);
+ }
+ }
+ // trim trailing whitespace
+ for (int i = content.size()-1; i >= 0; i--) {
+ Object obj = content.get(i);
+ if (obj instanceof Text) {
+ Text text = (Text) obj;
+ String s = trimTrailing(text.getText());
+ text.setText(s);
+ if (s.length() > 0)
+ break;
+ } else
+ break;
+ }
+ }
+
+ private static boolean isWhitespace(char c) {
+ // TODO Check definition
+ return c == ' ' || c == '\t' || c == '\r' || c == '\n';
+ }
+
+ private static String trimLeading(String s) {
+ int m = s.length();
+ for (int i = 0, n = m; i < n; i++) {
+ if (!isWhitespace(s.charAt(i))) {
+ m = i;
+ break;
+ }
+ }
+ return s.substring(m);
+ }
+
+ private static String trimTrailing(String s) {
+ int m = -1;
+ for (int max = s.length()-1, i = max; i >= 0; i--) {
+ if (!isWhitespace(s.charAt(i))) {
+ m = i;
+ break;
+ }
+ }
+ return s.substring(0, m+1);
+ }
+
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/impl/XDocumentType.java b/xpath-service/src/main/java/org/hudsonci/xpath/impl/XDocumentType.java
new file mode 100644
index 0000000..def309a
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/impl/XDocumentType.java
@@ -0,0 +1,304 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.hudsonci.xpath.impl;
+
+import org.w3c.dom.*;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public class XDocumentType implements DocumentType {
+
+ org.dom4j.DocumentType docType;
+ Node parent;
+
+ public XDocumentType(org.dom4j.DocumentType node, Node parent) {
+ docType = node;
+ this.parent = parent;
+ }
+
+ @Override
+ public String getTextContent() {
+ return null;
+ }
+
+ @Override
+ public String getNodeName() {
+ return getName();
+ }
+
+ @Override
+ public String getNodeValue() {
+ return null;
+ }
+
+ public String getName() {
+ return docType.getElementName();
+ }
+
+ public String getPublicId() {
+ return docType.getPublicID();
+ }
+
+ public String getSystemId() {
+ return docType.getSystemID();
+ }
+
+ public NamedNodeMap getEntities() {
+ return XNamedNodeMap.EMPTY;
+ }
+
+ public NamedNodeMap getNotations() {
+ return XNamedNodeMap.EMPTY;
+ }
+
+ public String getInternalSubset() {
+ return docType.asXML();
+ }
+
+ boolean isEq(String s1, String s2) {
+ if (s1 == s2) return true;
+ if (s1 == null || s2 == null) return false;
+ return s1.equals(s2);
+ }
+
+ @Override
+ public boolean isEqualNode(Node node) {
+ if (node.getNodeType() != Node.DOCUMENT_TYPE_NODE) return false;
+ DocumentType other = (DocumentType) node;
+ if (!isEq(getPublicId(), other.getPublicId())) return false;
+ if (!isEq(getSystemId(), other.getSystemId())) return false;
+ NamedNodeMap thisEnts = getEntities();
+ NamedNodeMap nodeEnts = other.getEntities();
+ int len = thisEnts.getLength();
+ if (len != nodeEnts.getLength()) return false;
+ for (int i = 0; i < len; i++) {
+ if (!thisEnts.item(i).isEqualNode(nodeEnts.item(i)))
+ return false;
+ }
+ return true;
+ }
+
+ public void setNodeValue(String string) throws DOMException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public short getNodeType() {
+ return Node.DOCUMENT_TYPE_NODE;
+ }
+
+ public Node getParentNode() {
+ return parent;
+ }
+
+ private static NodeList EMPTY = new NodeList() {
+
+ public Node item(int i) {
+ throw new IndexOutOfBoundsException(""+i);
+ }
+
+ public int getLength() {
+ return 0;
+ }
+ };
+
+ public NodeList getChildNodes() {
+ return EMPTY;
+ }
+
+ public Node getFirstChild() {
+ return null;
+ }
+
+ public Node getLastChild() {
+ return null;
+ }
+
+ public Node getPreviousSibling() {
+ NodeList list = parent.getChildNodes();
+ boolean found = false;
+ for (int i = list.getLength() - 1; i >= 0; i--) {
+ Node node = list.item(i);
+ if (found)
+ return node;
+ found = node == this;
+ }
+ return null;
+ }
+
+ public Node getNextSibling() {
+ NodeList list = parent.getChildNodes();
+ boolean found = false;
+ for (int i = 0, n = list.getLength(); i < n; i++) {
+ Node node = list.item(i);
+ if (found)
+ return node;
+ found = node == this;
+ }
+ return null;
+ }
+
+ private static final NamedNodeMap EMPTY_MAP = new NamedNodeMap() {
+
+ public Node getNamedItem(String string) {
+ return null;
+ }
+
+ public Node setNamedItem(Node node) throws DOMException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Node removeNamedItem(String string) throws DOMException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Node item(int i) {
+ throw new IndexOutOfBoundsException(""+i);
+ }
+
+ public int getLength() {
+ return 0;
+ }
+
+ public Node getNamedItemNS(String string, String string1) throws DOMException {
+ return null;
+ }
+
+ public Node setNamedItemNS(Node node) throws DOMException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Node removeNamedItemNS(String string, String string1) throws DOMException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ };
+
+ public NamedNodeMap getAttributes() {
+ return EMPTY_MAP;
+ }
+
+ public Document getOwnerDocument() {
+ return parent.getOwnerDocument();
+ }
+
+ public Node insertBefore(Node node, Node node1) throws DOMException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Node replaceChild(Node node, Node node1) throws DOMException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Node removeChild(Node node) throws DOMException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Node appendChild(Node node) throws DOMException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public boolean hasChildNodes() {
+ return false;
+ }
+
+ public Node cloneNode(boolean bln) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void normalize() {
+ }
+
+ public boolean isSupported(String string, String string1) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public String getNamespaceURI() {
+ return null;
+ }
+
+ public String getPrefix() {
+ return null;
+ }
+
+ public void setPrefix(String string) throws DOMException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public String getLocalName() {
+ return null;
+ }
+
+ public boolean hasAttributes() {
+ return false;
+ }
+
+ public String getBaseURI() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ private int docPos;
+ private int curPos;
+
+ public int getDocumentPosition(Node parent, Node node) {
+ if (parent == node)
+ return curPos;
+ NodeList children = parent.getChildNodes();
+ for (int i = 0, n = children.getLength(); i < n; i++) {
+ curPos++;
+ int found = getDocumentPosition(children.item(i), node);
+ if (found > 0)
+ return found;
+ }
+ return 0;
+ }
+
+ public int getDocumentPosition(Node node) {
+ curPos = 1;
+ return getDocumentPosition(getOwnerDocument(), node);
+ }
+
+ public short compareDocumentPosition(Node node) throws DOMException {
+ Document doc = getOwnerDocument();
+ if (docPos == 0)
+ docPos = getDocumentPosition(this);
+ int pos = getDocumentPosition(node);
+ return (short)(docPos < pos ? -1 : (docPos > pos ? 1 : 0));
+ }
+
+ public void setTextContent(String string) throws DOMException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public boolean isSameNode(Node node) {
+ return this == node;
+ }
+
+ public String lookupPrefix(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public boolean isDefaultNamespace(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public String lookupNamespaceURI(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Object getFeature(String string, String string1) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Object setUserData(String string, Object o, UserDataHandler udh) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Object getUserData(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/impl/XNamedNodeMap.java b/xpath-service/src/main/java/org/hudsonci/xpath/impl/XNamedNodeMap.java
new file mode 100644
index 0000000..699ce81
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/impl/XNamedNodeMap.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath.impl;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public class XNamedNodeMap implements NamedNodeMap {
+
+ public static final XNamedNodeMap EMPTY = new XNamedNodeMap();
+
+ private static class NSName {
+ String namespaceURI;
+ String localName;
+ String name;
+ NSName(String ns, String ln) {
+ namespaceURI = ns;
+ localName = ln;
+ }
+ NSName(String nm) {
+ name = nm;
+ }
+ public boolean equals(Object obj) {
+ if (!(obj instanceof NSName))
+ return false;
+ NSName other = (NSName) obj;
+ return localName != null
+ ? namespaceURI.equals(other.namespaceURI) && localName.equals(other.localName)
+ : name.equals(other.name);
+ }
+ public int hashCode() {
+ return localName != null
+ ? namespaceURI.hashCode() ^ localName.hashCode()
+ : name.hashCode();
+ }
+ }
+
+ Map<NSName,Node> map = new HashMap<NSName,Node>();
+
+ Node[] cache;
+
+ public Node getNamedItem(String name) {
+ return map.get(new NSName(name));
+ }
+
+ public Node setNamedItem(Node node) throws DOMException {
+ cache = null;
+ NSName name = new NSName(node.getNodeName());
+ return map.put(name, node);
+ }
+
+ public Node removeNamedItem(String name) throws DOMException {
+ cache = null;
+ return map.remove(new NSName(name));
+ }
+
+ public Node item(int i) {
+ if (cache == null)
+ cache = map.values().toArray(new Node[map.size()]);
+ return cache[i];
+ }
+
+ public int getLength() {
+ return map.size();
+ }
+
+ public Node getNamedItemNS(String namespaceURI, String localName) throws DOMException {
+ return map.get(new NSName(namespaceURI, localName));
+ }
+
+ public Node setNamedItemNS(Node node) throws DOMException {
+ cache = null;
+ NSName name = new NSName(node.getNamespaceURI(), node.getLocalName());
+ return map.put(name, node);
+ }
+
+ public Node removeNamedItemNS(String namespaceURI, String localName) throws DOMException {
+ cache = null;
+ NSName name = new NSName(namespaceURI, localName);
+ return map.remove(name);
+ }
+}
+
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/impl/XNamespaceAttribute.java b/xpath-service/src/main/java/org/hudsonci/xpath/impl/XNamespaceAttribute.java
new file mode 100644
index 0000000..936c9e0
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/impl/XNamespaceAttribute.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath.impl;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+import org.dom4j.*;
+
+/**
+ * Implement dom4j Attribute for namespace attributes, which in
+ * dom4j are sent as separate Namespace nodes after the element.
+ *
+ * @author Bob Foster
+ */
+public class XNamespaceAttribute implements Attribute {
+
+ String name;
+ String value;
+ Namespace ns;
+
+ public XNamespaceAttribute(String prefix, String value) {
+ this.name = "".equals(prefix) ? "xmlns" : "xmlns:"+prefix;
+ this.value = value;
+ this.ns = DocumentHelper.createNamespace("xmlns", "");
+ }
+
+ public Object clone() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public QName getQName() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Namespace getNamespace() {
+ return ns;
+ }
+
+ public void setNamespace(Namespace nmspc) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public String getNamespacePrefix() {
+ return ns.getPrefix();
+ }
+
+ public String getNamespaceURI() {
+ return "";
+ }
+
+ public String getQualifiedName() {
+ return name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Object getData() {
+ return value;
+ }
+
+ public void setData(Object o) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public boolean supportsParent() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Element getParent() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void setParent(Element elmnt) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Document getDocument() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void setDocument(Document dcmnt) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ public boolean hasContent() {
+ return true;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public String getText() {
+ return value;
+ }
+
+ public void setText(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public String getStringValue() {
+ return value;
+ }
+
+ public String getPath() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public String getPath(Element elmnt) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public String getUniquePath() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public String getUniquePath(Element elmnt) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public String asXML() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void write(Writer writer) throws IOException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public short getNodeType() {
+ return Attribute.ATTRIBUTE_NODE;
+ }
+
+ public String getNodeTypeName() {
+ return "ATTRIBUTE_NODE";
+ }
+
+ public Node detach() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public List selectNodes(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Object selectObject(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public List selectNodes(String string, String string1) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public List selectNodes(String string, String string1, boolean bln) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Node selectSingleNode(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public String valueOf(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Number numberValueOf(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public boolean matches(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public org.dom4j.XPath createXPath(String string) throws InvalidXPathException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Node asXPathResult(Element elmnt) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void accept(Visitor vstr) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+}
diff --git a/xpath-service/src/main/java/org/hudsonci/xpath/impl/XPathJavaImpl.java b/xpath-service/src/main/java/org/hudsonci/xpath/impl/XPathJavaImpl.java
new file mode 100644
index 0000000..e52980f
--- /dev/null
+++ b/xpath-service/src/main/java/org/hudsonci/xpath/impl/XPathJavaImpl.java
@@ -0,0 +1,365 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath.impl;
+
+import org.hudsonci.xpath.XPathAPI;
+import org.hudsonci.xpath.XNamespaceContext;
+import org.hudsonci.xpath.XVariableContext;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.xml.namespace.QName;
+import javax.xml.xpath.*;
+import org.hudsonci.xpath.XPathException;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Implementation of XPathAPI using javax.xml.xpath.
+ *
+ * @author Bob Foster
+ */
+public class XPathJavaImpl implements XPathAPI {
+
+ String expr;
+ String workingExpr;
+ javax.xml.xpath.XPath xpath;
+ XVariableContext varContext;
+ XNamespaceContext nsContext;
+ XPathExpression xpathExpr;
+
+ public XPathJavaImpl(String expr) {
+ this.expr = expr;
+ }
+
+ private class VarResolver implements XPathVariableResolver {
+
+ public Object resolveVariable(QName qname) {
+ try {
+ Object obj = varContext.getVariableValue(qname.getNamespaceURI(),
+ qname.getPrefix(), qname.getLocalPart());
+ if (obj instanceof org.dom4j.Node)
+ obj = nodeToNode((org.dom4j.Node) obj);
+ return obj;
+ } catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ }
+
+ private Dom2Dom d2d;
+
+ private Node nodeToNode(org.dom4j.Node d4jNode) throws XPathException {
+ d2d = new Dom2Dom();
+ return d2d.dom2Dom(d4jNode, true);
+ }
+
+ private org.dom4j.Node unmap(Node node) {
+ return d2d.getOriginalNode(node);
+ }
+
+ private XPathExpression getXPathExpression() throws XPathException {
+ if (xpathExpr == null) {
+ XPathFactory factory = XPathFactory.newInstance();
+ if (varContext != null)
+ factory.setXPathVariableResolver(new VarResolver());
+ xpath = factory.newXPath();
+ if (nsContext != null)
+ xpath.setNamespaceContext(nsContext);
+ try {
+ xpathExpr = xpath.compile(workingExpr);
+ } catch (XPathExpressionException ex) {
+ throw new XPathException(ex);
+ }
+ }
+ return xpathExpr;
+ }
+
+ /**
+ * Set variable context used when evaluating XPath expression.
+ * @param varContext
+ */
+ public void setVariableContext(XVariableContext varContext) {
+ this.varContext = varContext;
+ }
+
+ /**
+ * Get variable context.
+ * @return previously set variable context.
+ */
+ public XVariableContext getVariableContext() {
+ return varContext;
+ }
+
+ /**
+ * Get namespace context used when evaluating XPath expression.
+ * @param nsContext
+ */
+ public void setNamespaceContext(XNamespaceContext nsContext) {
+ this.nsContext = nsContext;
+ }
+
+ /**
+ * Get namespace context.
+ * @return previously set namespace context
+ */
+ public XNamespaceContext getNamespaceContext() {
+ return nsContext;
+ }
+
+ private Node getNode(Object xpathContext) throws XPathException {
+ // A common idiom in Jelly tests is to assign a document (or other node)
+ // to a variable and ask for an XPath using that variable to be
+ // evaluated with no context. This doesn't work in Xalan.
+ // We attempt to deal with the common case of this by rewriting
+ // an expression with exactly one node-valued variable, using the
+ // node as context and replacing it with '.' in the expression.
+ // A more complex scheme might attempt to extract all variables,
+ // find the outermost and rewrite the expression in terms of
+ // paths from the outermost node. Not yet.
+
+ workingExpr = expr;
+
+ org.dom4j.Node node = null;
+
+ if (xpathContext instanceof org.dom4j.Node)
+ node = (org.dom4j.Node) xpathContext;
+
+ else if (xpathContext == null) {
+ try {
+ // javax XPath doesn't like a null context. Try to fix.
+ Rewriter rewriter = new Rewriter();
+ Pair<String,org.dom4j.Node> pair = rewriter.rewriteExpression(expr, varContext, nsContext);
+ node = pair.getRight();
+ workingExpr = pair.getLeft();
+ } catch (Exception ex) {
+ throw new XPathException(ex);
+ }
+ }
+
+ if (node != null)
+ return nodeToNode(node);
+ else
+ throw new XPathException(xpathContext.getClass().getName()+" xpathContext must be subclass of org.dom4j.Node");
+ }
+
+ /**
+ * Evaluate expression and return an appropriate value, one of: Node, NodeList,
+ * String, Boolean or Double.
+ *
+ * @param xpathContext must be an org.dom4j.Node or null if expression contains
+ * a Node-valued variable that can be used to establish the context.
+ * @return result of evaluation
+ * @throws XPathException if errors detected
+ */
+ public Object evaluate(Object xpathContext) throws XPathException {
+ // javax.xml.xpath doesn't support "return whatever"
+ // hack around to satisfy Jelly
+ Node context = getNode(xpathContext);
+ XPathExpression xexpr = getXPathExpression();
+ Object obj = null;
+ try {
+ obj = xexpr.evaluate(context, XPathConstants.NODESET);
+ } catch (XPathExpressionException ex) {
+ try {
+ // Anything that will evaluate to a non-node will also evaluate as a string
+ obj = xexpr.evaluate(context);
+ } catch (XPathExpressionException ex1) {
+ throw new XPathException(ex1);
+ }
+ }
+ if (obj instanceof NodeList) {
+ NodeList list = (NodeList) obj;
+ int len = list.getLength();
+ if (len == 1)
+ return unmap(list.item(0));
+ return makeList(list);
+ }
+ // try some other alternatives
+ String s = ((String) obj).trim();
+ if ("true".equals(s))
+ return Boolean.TRUE;
+ if ("false".equals(s))
+ return Boolean.FALSE;
+ Double d = tryNumber(s);
+ if (d != null)
+ return d;
+ return s;
+ }
+
+ private Double tryNumber(String s) {
+ if ("INF".equals(s) || "+INF".equals(s))
+ s = "Infinity";
+ else if ("-INF".equals(s))
+ s = "-Infinity";
+ try {
+ return Double.valueOf(s);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+
+ }
+
+ /**
+ * Return boolean result of evaluating expression.
+ *
+ * @param xpathContext must be an org.dom4j.Node or null if expression contains
+ * a Node-valued variable that can be used to establish the context.
+ * @return boolean
+ * @throws XPathException if errors detected
+ */
+ public boolean booleanValueOf(Object xpathContext) throws XPathException {
+ Node context = getNode(xpathContext);
+ XPathExpression xexpr = getXPathExpression();
+ Object obj;
+ try {
+ obj = xexpr.evaluate(context, XPathConstants.BOOLEAN);
+ } catch (XPathExpressionException ex) {
+ throw new XPathException(ex);
+ }
+ if (obj instanceof Boolean)
+ return (Boolean) obj;
+ else
+ throw new XPathException("result not a Boolean, returned "+obj.getClass().getName());
+ }
+
+ /**
+ * Return double result of evaluating expression. Any number is converted to double.
+ * @param xpathContext must be an org.dom4j.Node or null if expression contains
+ * a Node-valued variable that can be used to establish the context.
+ * @return double
+ * @throws XPathException
+ */
+ public double numberValueOf(Object xpathContext) throws XPathException {
+ Node context = getNode(xpathContext);
+ XPathExpression xexpr = getXPathExpression();
+ Object obj;
+ try {
+ obj = xexpr.evaluate(context, XPathConstants.BOOLEAN);
+ } catch (XPathExpressionException ex) {
+ throw new XPathException(ex);
+ }
+ if (obj instanceof Double)
+ return (Double) obj;
+ else
+ throw new XPathException("result not a Double, returned "+obj.getClass().getName());
+ }
+
+ /**
+ * Return String result of evaluating expression.
+ * @param xpathContext must be an org.dom4j.Node or null if expression contains
+ * a Node-valued variable that can be used to establish the context.
+ * @return String
+ * @throws XPathException
+ */
+ public String stringValueOf(Object xpathContext) throws XPathException {
+ Node context = getNode(xpathContext);
+ XPathExpression xexpr = getXPathExpression();
+ try {
+ return xexpr.evaluate(xpathContext);
+ } catch (XPathExpressionException ex) {
+ throw new XPathException(ex);
+ }
+ }
+
+ /**
+ * Return Node result of evaluating expression. If the result has more than
+ * one Node, one of the Nodes is returned. If result has no Nodes,
+ * throws XPathException.
+ *
+ * @param xpathContext must be an org.dom4j.Node or null if expression contains
+ * a Node-valued variable that can be used to establish the context.
+ * @return Node
+ * @throws XPathException
+ */
+ public org.dom4j.Node selectSingleNode(Object xpathContext) throws XPathException {
+ Node context = getNode(xpathContext);
+ XPathExpression xexpr = getXPathExpression();
+ Object obj;
+ try {
+ obj = xexpr.evaluate(context, XPathConstants.NODE);
+ } catch (XPathExpressionException ex) {
+ throw new XPathException(ex);
+ }
+ if (obj instanceof Node)
+ return unmap((Node)obj);
+ if (obj instanceof NodeList) {
+ NodeList nodeList = (NodeList) obj;
+ if (nodeList.getLength() == 0)
+ throw new XPathException("returned empty NodeList");
+ return unmap(nodeList.item(0));
+ } else
+ throw new XPathException("result not a node, returned "+(obj == null ? "null" : obj.getClass().getName()));
+ }
+
+ /**
+ * Return List of Node result of evaluating expression.
+ *
+ * @param xpathContext must be an org.dom4j.Node or null if expression contains
+ * a Node-valued variable that can be used to establish the context.
+ * @return List of Nodes, may be empty
+ * @throws XPathException
+ */
+ public List selectNodes(Object xpathContext) throws XPathException {
+ Node context = getNode(xpathContext);
+ XPathExpression xexpr = getXPathExpression();
+ Object obj;
+ try {
+ obj = xexpr.evaluate(context, XPathConstants.NODESET);
+ } catch (XPathExpressionException ex) {
+ throw new XPathException(ex);
+ }
+ if (obj instanceof Node)
+ return makeList((Node) obj);
+ if (obj instanceof NodeList)
+ return makeList((NodeList) obj);
+ else if (obj == null)
+ return Collections.EMPTY_LIST;
+ else
+ throw new XPathException("result not a node list, returned "+obj.getClass().getName());
+ }
+
+ private List makeList(NodeList nodeList) {
+ List nodes = new ArrayList();
+ for (int i = 0, n = nodeList.getLength(); i < n; i++)
+ nodes.add(unmap(nodeList.item(i)));
+ return nodes;
+ }
+
+ private List makeList(Node node) {
+ org.dom4j.Node d4jNode = unmap((Node) node);
+ ArrayList<org.dom4j.Node> list = new ArrayList<org.dom4j.Node>();
+ list.add(d4jNode);
+ return list;
+ }
+
+ /**
+ * @return XPath expression
+ */
+ public String toString() {
+ return expr;
+ }
+
+ /**
+ * Reset the XPath expression. Used for debugging.
+ * @param expr
+ */
+ public void setExpr(String expr) {
+ this.expr = expr;
+ xpathExpr = null;
+ }
+}
diff --git a/xpath-service/src/test/java/org/hudsonci/xpath/TestDocumentSupport.java b/xpath-service/src/test/java/org/hudsonci/xpath/TestDocumentSupport.java
new file mode 100644
index 0000000..a5d3382
--- /dev/null
+++ b/xpath-service/src/test/java/org/hudsonci/xpath/TestDocumentSupport.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathFactory;
+import junit.framework.TestCase;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.io.SAXReader;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public class TestDocumentSupport extends TestCase {
+
+ public void printStdDocument(org.w3c.dom.Document doc) {
+ try {
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ StreamResult result = new StreamResult(new StringWriter());
+ DOMSource source = new DOMSource(doc);
+ transformer.transform(source, result);
+ String xmlString = result.getWriter().toString();
+ System.out.println(xmlString);
+ } catch (TransformerException ex) {
+ fail(ex.toString());
+ }
+ }
+
+ public org.w3c.dom.Document getStdDocument(String resourceName, boolean validating) {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setValidating(validating);
+ InputStream in = getClass().getResourceAsStream(resourceName);
+ assertTrue("Resource "+resourceName+" found", in != null);
+ try {
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ return builder.parse(in);
+ } catch (SAXException e) {
+ fail(e.toString());
+ } catch (ParserConfigurationException e) {
+ fail(e.toString());
+ } catch (IOException e) {
+ fail(e.toString());
+ } finally {
+ try { in.close(); } catch (Exception e) {;}
+ }
+ return null;
+ }
+
+ public Document getDom4jDocument(String resourceName, boolean validating) {
+ XMLReader xmlReader = XMLParser.getXMLParser().getReader(false);
+ SAXReader reader = new SAXReader(xmlReader);
+ InputStream in = getClass().getResourceAsStream(resourceName);
+ assertTrue("Resource "+resourceName+" found", in != null);
+ Document doc = null;
+
+ try {
+ doc = reader.read(in);
+ } catch (DocumentException e) {
+ fail("Can't read "+resourceName+" "+e);
+ } finally {
+ try { in.close(); } catch (Exception e) {;}
+ }
+
+ return doc;
+ }
+
+ public XPath getXPath() {
+ XPathFactory factory = XPathFactory.newInstance();
+ return factory.newXPath();
+ }
+
+ // So the "TestCase" contains at least one test
+ public void testDummy() {}
+
+
+
+}
diff --git a/xpath-service/src/test/java/org/hudsonci/xpath/TestDom4jToXDom.java b/xpath-service/src/test/java/org/hudsonci/xpath/TestDom4jToXDom.java
new file mode 100644
index 0000000..3556a89
--- /dev/null
+++ b/xpath-service/src/test/java/org/hudsonci/xpath/TestDom4jToXDom.java
@@ -0,0 +1,296 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath;
+
+import org.dom4j.Document;
+import org.hudsonci.xpath.impl.Dom2Dom;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public class TestDom4jToXDom extends TestDocumentSupport {
+
+ private static final boolean DEBUG = false;
+
+ private void compareDocs(String resourceName, org.w3c.dom.Document doc, org.w3c.dom.Document xdoc) {
+ boolean eq = XMLCompare.isEqual(doc, xdoc); // doc.isEqualNode(xdoc); See comments in XMLCompare
+ if (DEBUG && !eq) {
+ System.out.println("**Standard document "+resourceName+":");
+ printStdDocument(doc);
+ System.out.println("**Mapped document "+resourceName+":");
+ printStdDocument(xdoc);
+ }
+ assertTrue(resourceName+" XDoc from dom4j same as w3c Document", eq);
+ }
+
+ private void checkDocs(String resourceName) {
+ Document doc = getDom4jDocument(resourceName, false);
+
+ org.w3c.dom.Document xdoc = null;
+ try {
+ xdoc = (org.w3c.dom.Document) new Dom2Dom().dom2Dom(doc, false);
+ assertTrue(resourceName+" xdoc created", xdoc != null);
+ } catch (XPathException e) {
+ fail(resourceName+e);
+ }
+
+ compareDocs(resourceName, getStdDocument(resourceName, false), xdoc);
+ }
+
+ public void testNoNamespaceDoc() {
+ checkDocs("test1.xml");
+ }
+
+ public void testJellyDocs() {
+ checkDocs("_api.jelly");
+ checkDocs("_cli.jelly");
+ checkDocs("_entryForm.jelly");
+ checkDocs("_new.jelly");
+ checkDocs("_restart.jelly");
+ checkDocs("_safeRestart.jelly");
+ checkDocs("_script.jelly");
+ checkDocs("_scriptText.jelly");
+ checkDocs("accessDenied.jelly");
+ checkDocs("actions.jelly");
+ checkDocs("addUser.jelly");
+ checkDocs("advanced.jelly");
+ checkDocs("ajax.jelly");
+ checkDocs("ajaxBuildHistory.jelly");
+ checkDocs("ajaxBuildQueue.jelly");
+ checkDocs("ajaxExecutors.jelly");
+ checkDocs("ajaxMatrix.jelly");
+ checkDocs("ajaxRows.jelly");
+ checkDocs("all.jelly");
+ checkDocs("artifactList.jelly");
+ checkDocs("artifacts-index.jelly");
+ checkDocs("askRootPassword.jelly");
+ checkDocs("atom.jelly");
+ checkDocs("available.jelly");
+ checkDocs("badge.jelly");
+ checkDocs("ballColorTd.jelly");
+ checkDocs("bar.jelly");
+ checkDocs("block.jelly");
+ checkDocs("body.jelly");
+ checkDocs("booleanRadio.jelly");
+ checkDocs("build-permalink.jelly");
+ checkDocs("buildCaption.jelly");
+ checkDocs("buildHealth.jelly");
+ checkDocs("buildLink.jelly");
+ checkDocs("buildListTable.jelly");
+ checkDocs("buildProgressBar.jelly");
+ checkDocs("buildRangeLink.jelly");
+ checkDocs("buildStatusSummary.jelly");
+ checkDocs("buildTimeTrend.jelly");
+ checkDocs("builds.jelly");
+ checkDocs("cascadingDescriptorList.jelly");
+ checkDocs("cause.jelly");
+ checkDocs("causeOfDeath.jelly");
+ checkDocs("cc.xml.jelly");
+ checkDocs("changes.jelly");
+ checkDocs("checkUpdates.jelly");
+ checkDocs("checkbox.jelly");
+ checkDocs("column.jelly");
+ checkDocs("columnHeader.jelly");
+ checkDocs("combobox.jelly");
+ checkDocs("config-blockWhenDownstreamBuilding.jelly");
+ checkDocs("config-blockWhenUpstreamBuilding.jelly");
+ checkDocs("config-buildWrappers.jelly");
+ checkDocs("config-builders.jelly");
+ checkDocs("config-cleanWorkspace.jelly");
+ checkDocs("config-customWorkspace.jelly");
+ checkDocs("config-disableBuild.jelly");
+ checkDocs("config-publishers.jelly");
+ checkDocs("config-quietPeriod.jelly");
+ checkDocs("config-retryCount.jelly");
+ checkDocs("config-scm.jelly");
+ checkDocs("config-trigger.jelly");
+ checkDocs("config-upstream-pseudo-trigger.jelly");
+ checkDocs("config.jelly");
+ checkDocs("configure-advanced.jelly");
+ checkDocs("configure-common.jelly");
+ checkDocs("configure-entries.jelly");
+ checkDocs("configure.jelly");
+ checkDocs("configureExecutors.jelly");
+ checkDocs("confirm.jelly");
+ checkDocs("confirmDelete.jelly");
+ checkDocs("console.jelly");
+ checkDocs("consoleFull.jelly");
+ checkDocs("control.jelly");
+ checkDocs("custom-jnlp.jelly");
+ checkDocs("delete.jelly");
+ checkDocs("deleteConfirmationPanel.jelly");
+ checkDocs("description.jelly");
+ checkDocs("descriptionForm.jelly");
+ checkDocs("descriptorList.jelly");
+ checkDocs("descriptorRadioList.jelly");
+ checkDocs("detail.jelly");
+ checkDocs("digest.jelly");
+ checkDocs("dir.jelly");
+ checkDocs("disconnect.jelly");
+ checkDocs("downgrade.jelly");
+ checkDocs("dropdownDescriptorSelector.jelly");
+ checkDocs("dropdownList.jelly");
+ checkDocs("dropdownListBlock.jelly");
+ checkDocs("editDescription.jelly");
+ checkDocs("editTypeIcon.jelly");
+ checkDocs("editableComboBox.jelly");
+ checkDocs("editableComboBoxValue.jelly");
+ checkDocs("editableDescription.jelly");
+ checkDocs("entries.jelly");
+ checkDocs("entry.jelly");
+ checkDocs("enum.jelly");
+ checkDocs("enumSet.jelly");
+ checkDocs("error.jelly");
+ checkDocs("executors.jelly");
+ checkDocs("expandButton.jelly");
+ checkDocs("expandableTextbox.jelly");
+ checkDocs("feeds.jelly");
+ checkDocs("fingerprintCheck.jelly");
+ checkDocs("firstUser.jelly");
+ checkDocs("floatingBox.jelly");
+ checkDocs("foo.jelly");
+ checkDocs("footer.jelly");
+ checkDocs("form.jelly");
+ checkDocs("global.jelly");
+ checkDocs("hasPermission.jelly");
+ checkDocs("header.jelly");
+ checkDocs("help-launcher.jelly");
+ checkDocs("help.jelly");
+ checkDocs("helpArea.jelly");
+ checkDocs("hetero-list.jelly");
+ checkDocs("hetero-radio.jelly");
+ checkDocs("iconSize.jelly");
+ checkDocs("inProgress.jelly");
+ checkDocs("index.jelly");
+ checkDocs("installed.jelly");
+ checkDocs("invisibleEntry.jelly");
+ checkDocs("isAdmin.jelly");
+ checkDocs("isAdminOrTest.jelly");
+ checkDocs("jobDeleteForm.jelly");
+ checkDocs("jobLink.jelly");
+ checkDocs("jobpropertysummaries.jelly");
+ checkDocs("label.jelly");
+ checkDocs("layout.jelly");
+ checkDocs("legend.jelly");
+ checkDocs("levels.jelly");
+ checkDocs("link.jelly");
+ checkDocs("list.jelly");
+ checkDocs("listScmBrowsers.jelly");
+ checkDocs("load-statistics.jelly");
+ checkDocs("log.jelly");
+ checkDocs("logKeep.jelly");
+ checkDocs("login.jelly");
+ checkDocs("loginDialog.jelly");
+ checkDocs("loginError.jelly");
+ checkDocs("loginLink.jelly");
+ checkDocs("main-panel.jelly");
+ checkDocs("main.jelly");
+ checkDocs("manage.jelly");
+ checkDocs("markOffline.jelly");
+ checkDocs("matrix.jelly");
+ checkDocs("message.jelly");
+ checkDocs("myViewTabs.jelly");
+ checkDocs("nested.jelly");
+ checkDocs("new.jelly");
+ checkDocs("newInstanceDetail.jelly");
+ checkDocs("newJob.jelly");
+ checkDocs("newJobDetail.jelly");
+ checkDocs("newView.jelly");
+ checkDocs("newViewDetail.jelly");
+ checkDocs("noJob.jelly");
+ checkDocs("noPrincipal.jelly");
+ checkDocs("noWorkspace.jelly");
+ checkDocs("node.jelly");
+ checkDocs("nodepropertysummaries.jelly");
+ checkDocs("opensearch.xml.jelly");
+ checkDocs("option.jelly");
+ checkDocs("optionalBlock.jelly");
+ checkDocs("optionalProperty.jelly");
+ checkDocs("outline.jelly");
+ checkDocs("pane.jelly");
+ checkDocs("password.jelly");
+ checkDocs("permalinks.jelly");
+ checkDocs("prepareDatabinding.jelly");
+ checkDocs("progressBar.jelly");
+ checkDocs("progressiveText.jelly");
+ checkDocs("project-changes.jelly");
+ checkDocs("projectActionFloatingBox.jelly");
+ checkDocs("projectRelationship-help.jelly");
+ checkDocs("projectRelationship.jelly");
+ checkDocs("projectView.jelly");
+ checkDocs("projectViewNested.jelly");
+ checkDocs("projectViewRow.jelly");
+ checkDocs("property.jelly");
+ checkDocs("propertyTable.jelly");
+ checkDocs("queue.jelly");
+ checkDocs("radio.jelly");
+ checkDocs("radioBlock.jelly");
+ checkDocs("readOnlyTextbox.jelly");
+ checkDocs("rename.jelly");
+ checkDocs("repeatable.jelly");
+ checkDocs("repeatableDeleteButton.jelly");
+ checkDocs("repeatableProperty.jelly");
+ checkDocs("richtextarea.jelly");
+ checkDocs("rightspace.jelly");
+ checkDocs("row.jelly");
+ checkDocs("rowSet.jelly");
+ checkDocs("rss20.jelly");
+ checkDocs("rssBar-with-iconSize.jelly");
+ checkDocs("rssBar.jelly");
+ checkDocs("rssHeader.jelly");
+ checkDocs("scriptConsole.jelly");
+ checkDocs("search-failed.jelly");
+ checkDocs("searchPopup.jelly");
+ checkDocs("section.jelly");
+ checkDocs("select.jelly");
+ checkDocs("setIconSize.jelly");
+ checkDocs("side-panel.jelly");
+ checkDocs("sidepanel.jelly");
+ checkDocs("sidepanel2.jelly");
+ checkDocs("signup.jelly");
+ checkDocs("signupWithFederatedIdentity.jelly");
+ checkDocs("sites.jelly");
+ checkDocs("slave-agent.jnlp.jelly");
+ checkDocs("slave-mode.jelly");
+ checkDocs("status.jelly");
+ checkDocs("submit.jelly");
+ checkDocs("success.jelly");
+ checkDocs("summary.jelly");
+ checkDocs("svn-password.jelly");
+ checkDocs("systemInfo.jelly");
+ checkDocs("tab.jelly");
+ checkDocs("tabBar.jelly");
+ checkDocs("table.jelly");
+ checkDocs("task.jelly");
+ checkDocs("taskWithDialog.jelly");
+ checkDocs("tasks.jelly");
+ checkDocs("test-result.jelly");
+ checkDocs("test1.xml");
+ checkDocs("textarea.jelly");
+ checkDocs("textbox.jelly");
+ checkDocs("threadDump.jelly");
+ checkDocs("upstream-downstream.jelly");
+ checkDocs("validateButton.jelly");
+ checkDocs("value.jelly");
+ checkDocs("viewTabs.jelly");
+ checkDocs("whoAmI.jelly");
+ checkDocs("wipeOutWorkspace.jelly");
+ checkDocs("wipeOutWorkspaceBlocked.jelly");
+ checkDocs("yui.jelly");
+
+ }
+}
diff --git a/xpath-service/src/test/java/org/hudsonci/xpath/TestXPathOnXNode.java b/xpath-service/src/test/java/org/hudsonci/xpath/TestXPathOnXNode.java
new file mode 100644
index 0000000..173dedc
--- /dev/null
+++ b/xpath-service/src/test/java/org/hudsonci/xpath/TestXPathOnXNode.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2012 Oracle Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *
+ * Bob Foster
+ *
+ *******************************************************************************/
+
+package org.hudsonci.xpath;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import org.dom4j.Document;
+import org.hudsonci.xpath.impl.Dom2Dom;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ *
+ * @author Bob Foster
+ */
+public class TestXPathOnXNode extends TestDocumentSupport {
+
+ Document doc;
+ org.w3c.dom.Document xdoc;
+
+ private void getDocuments(String resourceName, boolean validate) {
+ doc = getDom4jDocument(resourceName, false);
+ try {
+ xdoc = (org.w3c.dom.Document) new Dom2Dom().dom2Dom(doc, validate);
+ } catch (XPathException ex) {
+ fail("Can't get mapped document "+ex);
+ }
+ }
+
+ public void testNodeListXPathOnXNode() {
+ getDocuments("test1.xml", false);
+ XPath xpath = getXPath();
+ try {
+ Object obj = xpath.evaluate("/root/children/child", xdoc, XPathConstants.NODESET);
+ if (obj instanceof NodeList) {
+ NodeList list = (NodeList) obj;
+ int num = list.getLength();
+ assertTrue("NodeList has 2 nodes", num == 2);
+ Node node1 = list.item(0);
+ Node node2 = list.item(1);
+ String name1 = node1.getNodeName();
+ String name2 = node2.getNodeName();
+ assertTrue("result is 2 child nodes", "child".equals(name1) && "child".equals(name2));
+ org.w3c.dom.Document isDoc = node1.getOwnerDocument();
+ assertTrue("node belongs to document", xdoc == isDoc);
+ }
+ } catch (XPathExpressionException ex) {
+ fail("/root/children/child not accepted "+ex);
+ }
+ }
+
+ public void testNodeXPathOnXNode() {
+ getDocuments("test1.xml", false);
+ XPath xpath = getXPath();
+ try {
+ Object obj = xpath.evaluate("/root/children/child[@id=\"baz\"]", xdoc, XPathConstants.NODESET);
+ if (obj instanceof NodeList) {
+ NodeList list = (NodeList) obj;
+ int num = list.getLength();
+ assertTrue("NodeList has 1 node", num == 1);
+ Node node1 = list.item(0);
+ assertTrue("node is Node", node1 instanceof org.w3c.dom.Node);
+ String name1 = node1.getNodeName();
+ assertTrue("result is child node", "child".equals(name1));
+ }
+ } catch (XPathExpressionException ex) {
+ fail("/root/children/child[@id=\"baz\"] not accepted "+ex);
+ }
+ }
+
+ public void testStringXPathOnXNode() {
+ getDocuments("test1.xml", false);
+ XPath xpath = getXPath();
+ try {
+ Object obj = xpath.evaluate("/root/children/bool", xdoc, XPathConstants.STRING);
+ assertTrue("object is String", obj instanceof String);
+ assertTrue("string is \"true\"", "true".equals(obj));
+ } catch (XPathExpressionException ex) {
+ fail("/root/children/bool not accepted "+ex);
+ }
+ }
+
+ public void testNumberXPathOnXNode() {
+ getDocuments("test1.xml", false);
+ XPath xpath = getXPath();
+ try {
+ Object obj = xpath.evaluate("/root/children/num", xdoc, XPathConstants.NUMBER);
+ assertTrue("result is Double", obj instanceof Double);
+ assertTrue("result is 2.0", (Double)obj == 2.0D);
+ } catch (XPathExpressionException ex) {
+ fail("/root/children/num not accepted "+ex);
+ }
+ }
+
+ public void testBooleanXPathOnXNode() {
+ getDocuments("test1.xml", false);
+ XPath xpath = getXPath();
+ try {
+ Object obj = xpath.evaluate("/root/children/bool", xdoc, XPathConstants.BOOLEAN);
+ assertTrue("result is Boolean", obj instanceof Boolean);
+ assertTrue("result is true", (Boolean) obj);
+ } catch (XPathExpressionException ex) {
+ fail("/root/children/bool not accepted "+ex);
+ }
+ }
+}
diff --git a/xpath-service/src/test/java/org/hudsonci/xpath/XMLCompare.java b/xpath-service/src/test/java/org/hudsonci/xpath/XMLCompare.java
new file mode 100644
index 0000000..f6edf14
--- /dev/null
+++ b/xpath-service/src/test/java/org/hudsonci/xpath/XMLCompare.java
@@ -0,0 +1,266 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.hudsonci.xpath;
+
+import org.w3c.dom.*;
+
+/**
+ * Emulates W3C DOM Level 3 isEqualNode, with added output for debugging.
+ * Used to determine why nodes are not equal.
+ *
+ * @author Bob Foster
+ */
+public class XMLCompare {
+
+ private static final boolean DEBUG = true;
+
+ /**
+ * Compare two nodes according to the W3C DOM Level 3 specification.
+ *
+ * @see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-isEqualNode
+ *
+ * The 'self' variable takes the role that 'this'
+ * plays in the OOP version.
+ *
+ * NB: This does NOT give the same results as the javax implementation!
+ * Some documents succeed here that fail under isEqualNode. In all
+ * cases we've seen, when those documents are printed with an XSLT
+ * null transform, they are identical.
+ *
+ * Obviously, either Xerces applies some test not or not according to the
+ * spec or this class doesn't implement the spec correctly. In any case,
+ * this test is a decent indicator that the two classes will produce
+ * equivalent results when queried with XPath, so it is preferred.
+ *
+ * @param self
+ * @param node
+ * @return true iff nodes are equal
+ */
+ public static boolean isEqual(Node self, Node node) {
+ if (self instanceof Element)
+ return isEqualElement(self, node);
+ else if (self instanceof DocumentType)
+ return isEqualDocumentType(self, node);
+ return isEqualNode(self, node);
+ }
+
+ //-------------------- DocumentType ------------------------------
+
+ public static boolean isEqualDocumentType(Node s, Node node) {
+ if (node.getNodeType() != Node.DOCUMENT_TYPE_NODE)
+ return false;
+ DocumentType self = (DocumentType) s;
+ DocumentType other = (DocumentType) node;
+ if (!isEq(self.getPublicId(), other.getPublicId()))
+ return false;
+ if (!isEq(self.getSystemId(), other.getSystemId()))
+ return false;
+ NamedNodeMap thisEnts = self.getEntities();
+ NamedNodeMap nodeEnts = other.getEntities();
+ int len = thisEnts.getLength();
+ if (len != nodeEnts.getLength())
+ return false;
+ for (int i = 0; i < len; i++) {
+ if (!isEqualNode(thisEnts.item(i), nodeEnts.item(i)))
+ return false;
+ }
+ return isEqualNode(self, node);
+ }
+
+ //-------------------- Element -----------------------------------
+
+ private static void debugDumpAttrs(String what, NamedNodeMap attrs) {
+ System.out.println("** "+what+" attrs:");
+ int len = attrs.getLength();
+ for (int i = 0; i < len; i++) {
+ Attr attr = (Attr) attrs.item(i);
+ debugPrintNode(attr);
+ }
+ }
+
+ private static boolean debugDumpAttrs(Node self, Node node) {
+ NamedNodeMap thisAttrs = self.getAttributes();
+ debugDumpAttrs("this", thisAttrs);
+ Element other = (Element) node;
+ NamedNodeMap nodeAttrs = node.getAttributes();
+ debugDumpAttrs("node", nodeAttrs);
+ return false;
+ }
+
+ private static boolean debugIsEqualElement(Node self, Node node) {
+ if (node.getNodeType() != Node.ELEMENT_NODE)
+ return debugPrintNode(self) && debugPrintNode(node);
+ Element other = (Element) node;
+ NamedNodeMap thisAttrs = self.getAttributes();
+ NamedNodeMap nodeAttrs = node.getAttributes();
+ int len = thisAttrs.getLength();
+ int nlen = nodeAttrs.getLength();
+ if (len != nlen)
+ return debugDumpAttrs(self, node);
+ for (int i = 0; i < len; i++) {
+ Attr thisAttr = (Attr) thisAttrs.item(i);
+ Attr nodeAttr = null;
+ if (thisAttr.getLocalName() == null)
+ nodeAttr = (Attr) nodeAttrs.getNamedItem(thisAttr.getNodeName());
+ else
+ nodeAttr = (Attr) nodeAttrs.getNamedItemNS(thisAttr.getNamespaceURI(), thisAttr.getLocalName());
+ if (nodeAttr == null)
+ return debugDumpAttrs(self, node);
+ if (!thisAttr.isEqualNode(nodeAttr))
+ return false;
+ }
+ return isEqualNode(self, node);
+ }
+
+ private static boolean isEqualElement(Node self, Node node) {
+ if (DEBUG) return debugIsEqualElement(self, node);
+ else {
+ if (node.getNodeType() != Node.ELEMENT_NODE) return false;
+ Element other = (Element) node;
+ NamedNodeMap thisAttrs = self.getAttributes();
+ NamedNodeMap nodeAttrs = node.getAttributes();
+ int len = thisAttrs.getLength();
+ int nlen = nodeAttrs.getLength();
+ if (len != nlen) return false;
+ for (int i = 0; i < len; i++) {
+ Attr thisAttr = (Attr) thisAttrs.item(i);
+ Attr nodeAttr = null;
+ if (thisAttr.getLocalName() == null)
+ nodeAttr = (Attr) nodeAttrs.getNamedItem(thisAttr.getNodeName());
+ else
+ nodeAttr = (Attr) nodeAttrs.getNamedItemNS(thisAttr.getNamespaceURI(), thisAttr.getLocalName());
+ if (nodeAttr == null) return false;
+ if (!thisAttr.isEqualNode(nodeAttr)) return false;
+ }
+ return isEqualNode(self, node);
+ }
+ }
+
+ //-------------------- Node --------------------------------------
+
+ private static boolean isEq(String s1, String s2) {
+ return s1 == s1 || (s1 != null && s2 != null && s1.equals(s2));
+ }
+
+ private static String debugNodeType(Node node) {
+ switch (node.getNodeType()) {
+ case Node.ATTRIBUTE_NODE:
+ return "ATTRIBUTE_NODE";
+ case Node.CDATA_SECTION_NODE:
+ return "CDATA_SECTION_NODE";
+ case Node.COMMENT_NODE:
+ return "COMMENT_NODE";
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ return "DOCUMENT_FRAGMENT_NODE";
+ case Node.DOCUMENT_NODE:
+ return "DOCUMENT_NODE";
+ case Node.DOCUMENT_TYPE_NODE:
+ return "DOCUMENT_TYPE_NODE";
+ case Node.ELEMENT_NODE:
+ return "ELEMENT_NODE";
+ case Node.ENTITY_NODE:
+ return "ENTITY_NODE";
+ case Node.ENTITY_REFERENCE_NODE:
+ return "ENTITY_REFERENCE_NODE";
+ case Node.NOTATION_NODE:
+ return "NOTATION_NODE";
+ case Node.PROCESSING_INSTRUCTION_NODE:
+ return "PROCESSING_INSTRUCTION_NODE";
+ case Node.TEXT_NODE:
+ return "TEXT_NODE";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
+ private static boolean debugPrintNode(Node node) {
+ System.out.println("");
+ System.out.println(" nodeType="+debugNodeType(node));
+ System.out.println(" nodeName=\""+node.getNodeName()+"\"");
+ System.out.println(" nodeValue=\""+node.getNodeValue()+"\"");
+ System.out.println(" prefix=\""+node.getPrefix()+"\"");
+ System.out.println(" localName=\""+node.getLocalName()+"\"");
+ System.out.println(" namespaceURI=\""+node.getNamespaceURI()+"\"");
+ System.out.println(" numChildren="+node.getChildNodes().getLength());
+ return false;
+ }
+
+ private static void debugPrintChildTypes(Node node) {
+ NodeList nodeChildren = node.getChildNodes();
+ for (int i = 0, n = nodeChildren.getLength(); i < n; i++) {
+ Node child = nodeChildren.item(i);
+ System.out.println(" child["+i+"] is "+debugNodeType(child)+" "+child.getNodeName());
+ }
+ }
+
+ private static boolean debugIsEqualNode(Node self, Node node) {
+ short thisType = self.getNodeType();;
+ short nodeType = node.getNodeType();
+ if (thisType != nodeType)
+ return debugPrintNode(self) && debugPrintNode(node);
+ String thisVal = self.getPrefix();
+ String nodeVal = node.getPrefix();
+ if (!isEq(thisVal, nodeVal))
+ return debugPrintNode(self) && debugPrintNode(node);
+ thisVal = self.getNodeName();
+ nodeVal = node.getNodeName();
+ if (!isEq(thisVal, nodeVal))
+ return debugPrintNode(self) && debugPrintNode(node);
+ thisVal = self.getNodeValue();
+ nodeVal = node.getNodeValue();
+ if (!isEq(thisVal, nodeVal))
+ return debugPrintNode(self) && debugPrintNode(node);
+ thisVal = self.getLocalName();
+ nodeVal = node.getLocalName();
+ if (!isEq(thisVal, nodeVal))
+ return false;
+ thisVal = self.getNamespaceURI();
+ nodeVal = node.getNamespaceURI();
+ if (!isEq(thisVal, nodeVal))
+ return debugPrintNode(self) && debugPrintNode(node);
+ NodeList thisChildren = self.getChildNodes();
+ NodeList nodeChildren = node.getChildNodes();
+ int len = thisChildren.getLength();
+ int nlen = nodeChildren.getLength();
+ if (len != nlen) {
+ debugPrintNode(self);
+ debugPrintChildTypes(self);
+ debugPrintNode(node);
+ debugPrintChildTypes(node);
+ return false;
+ }
+ for (int i = 0; i < len; i++) {
+ if (!isEqualNode(thisChildren.item(i), nodeChildren.item(i)))
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean isEqualNode(Node self, Node node) {
+ if (!DEBUG) {
+
+ if (self.getNodeType() != node.getNodeType()) return false;
+ if (!isEq(self.getPrefix(), node.getPrefix())) return false;
+ if (!isEq(self.getNodeName(), node.getNodeName())) return false;
+ if (!isEq(self.getNodeValue(), node.getNodeValue())) return false;
+ if (!isEq(self.getLocalName(), node.getLocalName())) return false;
+ if (!isEq(self.getNamespaceURI(), node.getNamespaceURI())) return false;
+ NodeList thisChildren = self.getChildNodes();
+ NodeList nodeChildren = node.getChildNodes();
+ int len = thisChildren.getLength();
+ int nlen = nodeChildren.getLength();
+ if (len != nlen) return false;
+ for (int i = 0; i < len; i++) {
+ if (!thisChildren.item(i).isEqualNode(nodeChildren.item(i)))
+ return false;
+ }
+ return true;
+
+ } else
+ return debugIsEqualNode(self, node);
+ }
+
+}
diff --git a/xpath-service/src/test/java/org/hudsonci/xpath/XMLParser.java b/xpath-service/src/test/java/org/hudsonci/xpath/XMLParser.java
new file mode 100644
index 0000000..c490c12
--- /dev/null
+++ b/xpath-service/src/test/java/org/hudsonci/xpath/XMLParser.java
@@ -0,0 +1,61 @@
+package org.hudsonci.xpath;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+/**
+ * A class that creates parsers like Jelly does.
+ *
+ * @author Bob Foster
+ */
+public class XMLParser {
+
+ SAXParser parser;
+ SAXParserFactory factory;
+ XMLReader reader;
+ public static final XMLParser instance = new XMLParser();
+
+ private XMLParser() {
+ }
+
+ public static XMLParser getXMLParser() {
+ return instance;
+ }
+
+ public SAXParser getParser(boolean validating) {
+ // Return the parser we already created (if any)
+ if (parser != null) {
+ return parser;
+ }
+ try {
+ if (factory == null)
+ factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ factory.setValidating(validating);
+ parser = factory.newSAXParser();
+ return (parser);
+ } catch (Exception e) {
+ System.out.println("Cannot get SAXParser " + e);
+ return null;
+ }
+ }
+
+ public XMLReader getReader(boolean validating) {
+ try {
+ return (getXMLReader(validating));
+ } catch (SAXException e) {
+ System.out.println("Cannot get XMLReader " + e);
+ return null;
+ }
+ }
+
+ public synchronized XMLReader getXMLReader(boolean validating) throws SAXException {
+ if (reader == null) {
+ reader = getParser(validating).getXMLReader();
+ reader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
+ }
+ return reader;
+ }
+}
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/_api.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/_api.jelly
new file mode 100644
index 0000000..32f7695
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/_api.jelly
@@ -0,0 +1,36 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <h2>Other Useful URLs</h2>
+ <dl>
+ <dt><a href="../buildNumber">Build number</a></dt>
+ <dd>
+ This URL returns the build number in <tt>text/plain</tt> format.
+ </dd>
+ <dt><a href="../buildTimestamp">Build timestamp</a></dt>
+ <dd>
+ This URL returns the build timestamp. You can also use the <tt>format</tt> query parameter
+ to control the date format, which follows
+ <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/text/SimpleDateFormat.html">the <tt>SimpleDateFormat</tt> format pattern</a>.
+ (<a href="../buildTimestamp?format=yyyy/MM/dd">example</a>)
+ You can also use the <tt>Accept-Language</tt> HTTP header to control the locale
+ in which the date is formatted.
+ </dd>
+ </dl>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/_cli.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/_cli.jelly
new file mode 100644
index 0000000..d7c974e
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/_cli.jelly
@@ -0,0 +1,35 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout norefresh="true">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <h1>
+ <img src="${imagesURL}/48x48/terminal.png" alt=""/>
+ ${%Hudson CLI}
+ </h1>
+ <p>
+ ${%blurb(rootURL)}
+ </p>
+ <pre style="color: white; background-color:black; padding:1em; font-weight: bold">java -jar <a
+ style="color: white"
+ href="jnlpJars/hudson-cli.jar">hudson-cli.jar</a> -s ${h.inferHudsonURL(request)} help</pre>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/_entryForm.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/_entryForm.jelly
new file mode 100644
index 0000000..52f5cd0
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/_entryForm.jelly
@@ -0,0 +1,81 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe
+#
+#
+#************************************************************************** -->
+
+
+<!-- tag file sed by both signup.jelly and addUser.jelly -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <l:layout norefresh="true" title="${%Sign up}">
+ <l:header>
+ <style>
+ <!-- match width with captcha image -->
+ INPUT {
+ width:200px;
+ }
+ </style>
+ </l:header>
+ <l:hasPermission permission="${app.READ}" it="${host}">
+ <st:include page="sidepanel.jelly" it="${host}" />
+ </l:hasPermission>
+ <l:main-panel>
+ <h1>${title}</h1>
+ <div style="margin: 2em;">
+ <j:if test="${data.errorMessage!=null}">
+ <div class="error" style="margin-bottom:1em">
+ ${data.errorMessage}
+ </div>
+ </j:if>
+ <form action="${rootURL}/securityRealm/${action}" method="post" style="text-size:smaller">
+ <table>
+ <tr>
+ <td>${%Username}:</td>
+ <td><input type="text" name="username" id="username" value="${data.username}" /></td>
+ </tr>
+ <tr>
+ <td>${%Password}:</td>
+ <td><input type="password" name="password1" value="${data.password1}" /></td>
+ </tr>
+ <tr>
+ <td>${%Confirm password}:</td>
+ <td><input type="password" name="password2" value="${data.password2}" /></td>
+ </tr>
+ <tr>
+ <td>${%Full name}:</td>
+ <td><input type="text" name="fullname" value="${data.fullname}" /></td>
+ </tr>
+ <tr>
+ <td>${%E-mail address}:</td>
+ <td><input type="text" name="email" value="${data.email}" /></td>
+ </tr>
+ <j:if test="${captcha}">
+ <tr>
+ <td>${%Enter text as shown}:</td>
+ <td>
+ <input type="text" name="captcha" autocomplete="off" /><br />
+ <img src="${rootURL}/securityRealm/captcha" alt="[captcha]"/>
+ </td>
+ </tr>
+ </j:if>
+ </table>
+ <f:submit value="${title}" />
+ <script>
+ $('username').focus();
+ </script>
+ </form>
+ </div>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/_new.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/_new.jelly
new file mode 100644
index 0000000..1f2e972
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/_new.jelly
@@ -0,0 +1,44 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ 2nd page in the "new slave" page for displaying the entire configuration entries for the selected job type.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout"
+ xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <l:layout norefresh="true" permission="${app.ADMINISTER}">
+ <st:include page="sidepanel.jelly"/>
+ <l:main-panel>
+ <f:form method="post" action="doCreateItem">
+ <f:entry title="${%Name}" help="/help/system-config/master-slave/name.html">
+ <f:textbox name="name" value="${request.getParameter('name')}" clazz="required" checkMessage="${%Name is mandatory}"/>
+ </f:entry>
+
+ <!-- main body of the configuration -->
+ <j:set var="it" value="${null}" />
+ <st:include class="${requestScope.descriptor.clazz}" page="configure-entries.jelly" />
+
+ <f:block>
+ <input type="hidden" name="type" value="${request.getParameter('mode')}"/>
+
+ <f:submit value="${%Save}"/>
+ </f:block>
+ </f:form>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/_restart.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/_restart.jelly
new file mode 100644
index 0000000..9f83feb
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/_restart.jelly
@@ -0,0 +1,30 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+
+<!-- Delete view -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="Restart Hudson">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <form method="post" action="restart">
+ ${%Are you sure about restarting Hudson?}
+ <f:submit value="${%Yes}" />
+ </form>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/_safeRestart.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/_safeRestart.jelly
new file mode 100644
index 0000000..8cc4758
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/_safeRestart.jelly
@@ -0,0 +1,30 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+
+<!-- Delete view -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="Safely Restart Hudson">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <form method="post" action="safeRestart">
+ ${%Are you sure about restarting Hudson? Hudson will restart once all running jobs are finished.}
+ <f:submit value="${%Yes}" />
+ </form>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/_script.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/_script.jelly
new file mode 100644
index 0000000..0555bda
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/_script.jelly
@@ -0,0 +1,59 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Winston Prakash
+#
+#************************************************************************** -->
+
+
+<!--
+ Called from doScript() to display the execution result and the form.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+
+
+ <j:if test="${app.scriptSupport == null}">
+ <l:layout norefresh="true">
+ <st:include page="sidepanel.jelly" />
+
+ <l:main-panel>
+ <table style="padding-left: 2em;" >
+ <h1>${%Script Console}</h1>
+ <h2>${app.scriptSupport}</h2>
+ <h4>No script support plugins installed.</h4>
+ </table>
+ </l:main-panel>
+ </l:layout>
+ </j:if>
+
+
+ <j:if test="${app.scriptSupport != null}">
+ <j:set var="node" value="master" />
+ <st:include from="${app.scriptSupport.descriptor}" page="${app.scriptSupport.descriptor.configPage}"/>
+ </j:if>
+
+ <!--
+ <j:if test="${size(h.scriptSupportDescriptors) > 0}">
+ <f:dropdownList name="scriptSupport" title="${%Script Type}">
+
+ <j:forEach var="descriptor" items="${h.scriptSupportDescriptors}" varStatus="loop">
+ <f:dropdownListBlock title="${descriptor.displayName}" value="${loop.index}"
+ selected="${descriptor==it.scriptSupport.descriptor}"
+ staplerClass="${descriptor.clazz.name}">
+ <st:include from="${descriptor}" page="${descriptor.configPage}"/>
+ </f:dropdownListBlock>
+ </j:forEach>
+ </f:dropdownList>
+ </j:if>
+ -->
+
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/_scriptText.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/_scriptText.jelly
new file mode 100644
index 0000000..f95ef8d
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/_scriptText.jelly
@@ -0,0 +1,23 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Red Hat, Inc.
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Called from doScriptText() to display the execution result.
+-->
+<?jelly escape-by-default='false'?>
+<st:compress xmlns:j="jelly:core" xmlns:st="jelly:stapler">
+<st:contentType value="text/plain;charset=UTF-8" />${output}</st:compress>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/accessDenied.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/accessDenied.jelly
new file mode 100644
index 0000000..5e4b80d
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/accessDenied.jelly
@@ -0,0 +1,52 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <l:layout norefresh="true">
+ <!-- don't include sidepanel.jelly, which could reveal information -->
+ <l:header title="${%Hudson Login}" />
+ <l:side-panel />
+ <l:main-panel>
+ <h1>${%Access Denied}</h1>
+ <!-- TODO: message is not human readable. define a subclass -->
+ <p class="error"><st:out value="${exception.message}"/></p>
+
+ <j:if test="${h.isAnonymous()}">
+ <div style="margin: 2em;">
+ <!-- login form -->
+ <form action="j_security_check" method="post" style="text-size:smaller">
+ <table>
+ <tr>
+ <td>${%User}:</td>
+ <td><input type="text" name="j_username" id="j_username" /></td>
+ </tr>
+ <tr>
+ <td>${%Password}:</td>
+ <td><input type="password" name="j_password" /></td>
+ </tr>
+ </table>
+ <f:submit value="${%login}" />
+ <script>
+ $('j_username').focus();
+ </script>
+ </form>
+ </div>
+ </j:if>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/actions.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/actions.jelly
new file mode 100644
index 0000000..d82599d
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/actions.jelly
@@ -0,0 +1,29 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Matthew R. Harrah
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Side panel for the build view.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:forEach var="action" items="${it.actions}">
+ <j:if test="${action.iconFileName!=null}">
+ <l:task icon="${h.getIconFilePath(action)}" title="${action.displayName}"
+ href="${h.getActionUrl(it.url,action)}" />
+ </j:if>
+ </j:forEach>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/addUser.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/addUser.jelly
new file mode 100644
index 0000000..3c4fd0b
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/addUser.jelly
@@ -0,0 +1,24 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Page for admin to create a new user
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <local:_entryForm host="${it}" title="${%Create User}" action="createAccountByAdmin" captcha="${false}" xmlns:local="/hudson/security/HudsonPrivateSecurityRealm" />
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/advanced.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/advanced.jelly
new file mode 100644
index 0000000..70244f5
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/advanced.jelly
@@ -0,0 +1,40 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Expandable section that shows "advanced..." button by default.
+ Upon clicking it, a section unfolds, and the HTML rendered by the body of this tag
+ appears.
+ <st:attribute name="title">
+ Custom button title.
+ </st:attribute>
+ </st:documentation>
+
+ <tr><td/><td/>
+ <td>
+ <div class="advancedLink">
+ <input type="button" value="${attrs.title != null ? attrs.title : 'Advanced...'}" class="advancedButton" />
+ </div>
+ <table class="advancedBody"><tbody>
+ <!-- this is the hidden portion that hosts the "advanced" part. Contents will be moved to the master table when "advanced..." is clicked -->
+ <d:invokeBody/>
+ </tbody></table>
+ </td>
+ </tr>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/ajax.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/ajax.jelly
new file mode 100644
index 0000000..180ab90
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/ajax.jelly
@@ -0,0 +1,48 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ If the tag is used during the full HTML page generation, <ajax> tag becomes
+ no-op and simply invokes its body.
+
+ If the page is used as a top-level tag, it sets up the environment
+ for generating partial HTML contents (which can be then injected into the existing
+ page via client-side script.)
+
+ See MatrixProject/index.jelly and ajaxMatrix.jelly for how to use this tag.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form" xmlns:p="/lib/hudson/project">
+ <j:choose>
+ <j:when test="${rootURL!=null}">
+ <!-- no envelope needed, since this is called during full HTML rendering. -->
+ <d:invokeBody/>
+ </j:when>
+ <j:otherwise>
+ <!-- called to generate partial HTML. set up HTML headers and etc -->
+ <!-- copied from layout.jelly -->
+ <st:contentType value="text/html;charset=UTF-8" />
+ <j:set var="rootURL" value="${request.contextPath}" />
+ <j:new var="h" className="hudson.Functions" /><!-- instead of JSP functions -->
+ <j:set var="resURL" value="${rootURL}${h.resourcePath}" />
+ <j:set var="imagesURL" value="${rootURL}${h.resourcePath}/images" />
+ <j:set var="ajax" value="true"/>
+
+ <d:invokeBody/>
+ </j:otherwise>
+ </j:choose>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxBuildHistory.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxBuildHistory.jelly
new file mode 100644
index 0000000..49ac680
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxBuildHistory.jelly
@@ -0,0 +1,27 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:ajax>
+ <table>
+ <st:include page="entries.jelly" />
+ </table>
+ </l:ajax>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxBuildQueue.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxBuildQueue.jelly
new file mode 100644
index 0000000..675e036
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxBuildQueue.jelly
@@ -0,0 +1,26 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Used to asynchronously update build queue
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form">
+ <l:ajax>
+ <t:queue items="${it.queueItems}" />
+ </l:ajax>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxExecutors.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxExecutors.jelly
new file mode 100644
index 0000000..8d4a8fd
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxExecutors.jelly
@@ -0,0 +1,26 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Tom Huybrechts
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Used to asynchronously update executor queue
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form">
+ <l:ajax>
+ <t:executors computers="${it.computers}"/>
+ </l:ajax>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxMatrix.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxMatrix.jelly
new file mode 100644
index 0000000..27bc31c
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxMatrix.jelly
@@ -0,0 +1,40 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Used to asynchronously update executor queue
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form" xmlns:p="/lib/hudson/project">
+ <l:ajax>
+ <p:matrix autoRefresh="true">
+ <j:choose>
+ <j:when test="${p==null}">
+ <img src="${imagesURL}/24x24/grey.png" tooltip="${%Not configured}" alt="${%Not configured}"/>
+ </j:when>
+ <j:otherwise>
+ <a href="${p.shortUrl}">
+ <img src="${imagesURL}/24x24/${p.buildStatusUrl}" tooltip="${p.iconColor.description}" alt="${p.iconColor.description}"/>
+ <j:if test="${empty(o.x) and empty(o.y)}">
+ ${p.combination.toString(o.z)}
+ </j:if>
+ </a>
+ </j:otherwise>
+ </j:choose>
+ </p:matrix>
+ </l:ajax>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxRows.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxRows.jelly
new file mode 100644
index 0000000..f2fa1cd
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/ajaxRows.jelly
@@ -0,0 +1,36 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Used to render the folder content through an AJAX call.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:ajax>
+ <t:setIconSize/>
+ <table><!-- throw away table tag to group rows together -->
+ <j:set var="depth" value="${request.getParameter('depth')}" />
+ <j:set var="indenter" value="${it.createFixedIndenter(depth)}" />
+ <j:forEach var="v" items="${it.views}">
+ <t:projectViewNested />
+ </j:forEach>
+ <j:forEach var="job" items="${it.items}">
+ <t:projectViewRow jobBaseUrl="${rootURL}/${it.url}" />
+ </j:forEach>
+ </table>
+ </l:ajax>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/all.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/all.jelly
new file mode 100644
index 0000000..f710e28
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/all.jelly
@@ -0,0 +1,27 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Used by buildHistory.jelly to lazily fetch the complete build records.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout">
+ <l:ajax>
+ <j:set var="all" value="${true}"/>
+ <st:include page="index.jelly" />
+ </l:ajax>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/artifactList.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/artifactList.jelly
new file mode 100644
index 0000000..2d13356
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/artifactList.jelly
@@ -0,0 +1,83 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Romain Seguy
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Generates a listing of the build artifacts.
+ Depending on the size of the artifact, this will either produce a list or a link to the directory view.
+
+ <st:attribute name="build" type="hudson.model.Build" use="required">
+ Build object for which the artifacts are displayed
+ </st:attribute>
+ <st:attribute name="caption" use="required">
+ Human readable title text
+ </st:attribute>
+ <st:attribute name="baseURL">
+ If the hyperlink to artifacts are at another URL, specify the prefix.
+ </st:attribute>
+ </st:documentation>
+ <j:if test="${!h.isArtifactsPermissionEnabled() or h.isArtifactsPermissionEnabled() and h.hasPermission(it,attrs.permission)}">
+ <j:set var="artifacts" value="${build.getArtifactsUpTo(build.TREE_CUTOFF+1)}" />
+ <j:if test="${!build.building and !empty(artifacts)}">
+ <t:summary icon="package.png">
+ <a href="${baseURL}artifact/">${caption}</a>
+ <j:choose>
+ <j:when test="${size(artifacts) le build.LIST_CUTOFF}">
+ <!-- if not too many, just list them -->
+ <ul>
+ <j:forEach var="f" items="${artifacts}">
+ <li>
+ <a href="${baseURL}artifact/${f.href}">${f.displayPath}</a>
+ <st:nbsp/>
+ <a href="${baseURL}artifact/${f.href}/*fingerprint*/"><img src="${imagesURL}/16x16/fingerprint.png" alt="[fingerprint]" /></a>
+ </li>
+ </j:forEach>
+ </ul>
+ </j:when>
+ <j:when test="${size(artifacts) le build.TREE_CUTOFF}">
+ <!-- otherwise (unless way too many) use a tree view -->
+ <l:yui module="treeview"/>
+ <link rel="stylesheet" href="${resURL}/scripts/yui/treeview/assets/skins/sam/treeview.css" type="text/css"/>
+ <link rel="stylesheet" href="${resURL}/scripts/yui/fonts/fonts-min.css" type="text/css"/>
+ <style type="text/css">#artifact-tree td { vertical-align:middle; }</style>
+ <div id="artifact-tree"></div>
+ <script language="javascript">// &lt;![CDATA[
+ YAHOO.util.Event.onContentReady('artifact-tree', function () {
+ var artifactTree = new YAHOO.widget.TreeView('artifact-tree');
+ var artifactRoot = new YAHOO.widget.TextNode('${h.jsStringEscape('%View')}',
+ artifactTree.getRoot(), false);
+ <j:forEach var="e" items="${artifacts.getTree().entrySet()}">
+ <j:set var="f" value="${e.key}"/>
+ var ${f.treeNodeId} = new YAHOO.widget.TextNode(
+ '${h.jsStringEscape(f.fileName)}', ${e.value?:'artifactRoot'}, false);
+ <j:if test="${f.href!=null}">
+ <!-- Assign href property instead of passing to constructor above,
+ as constructor does urlencoding, but f.href is already encoded -->
+ ${f.treeNodeId}.href = '${baseURL}artifact/${h.jsStringEscape(f.href)}';
+ </j:if>
+ </j:forEach>
+ artifactTree.draw();
+ });
+ // ]]&gt;</script>
+ </j:when>
+ <!-- otherwise just show link to directory browser -->
+ </j:choose>
+ </t:summary>
+ </j:if>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/artifacts-index.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/artifacts-index.jelly
new file mode 100644
index 0000000..be30021
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/artifacts-index.jelly
@@ -0,0 +1,35 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Romain Seguy
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <j:if test="${!h.isArtifactsPermissionEnabled() or h.isArtifactsPermissionEnabled() and h.hasPermission(it.ARTIFACTS)}">
+ <l:layout title="${it.fullDisplayName} Artifacts">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <t:buildCaption>
+ ${%Build Artifacts}
+ </t:buildCaption>
+ <ul>
+ <j:forEach var="f" items="${it.artifacts}">
+ <li><a href="artifact/${f.href}">${f.displayPath}</a></li>
+ </j:forEach>
+ </ul>
+ </l:main-panel>
+ </l:layout>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/askRootPassword.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/askRootPassword.jelly
new file mode 100644
index 0000000..36662ab
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/askRootPassword.jelly
@@ -0,0 +1,56 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <l:layout title="${%Permission Denied}">
+ <l:header />
+ <l:side-panel />
+ <l:main-panel>
+ <h1>
+ <img src="${imagesURL}/48x48/secure.png" width="48" height="48" alt=""/>
+ ${%Permission Denied}
+ </h1>
+ <div>
+ ${%blurb}
+
+ <f:form method="post" action="start">
+ <f:entry title="${%Username}">
+ <f:textbox name="username" value="root" />
+ </f:entry>
+
+ <f:entry title="${%Password}">
+ <f:password name="password" />
+ </f:entry>
+
+ <f:block>
+ <f:submit value="${%OK}" style="margin-top:1em;" />
+ </f:block>
+ </f:form>
+
+ <input type="button" value="${%See errors...}" onclick="showDetails()" id="button"/>
+ <pre id="details" style="display:none"><st:out value="${message}"/></pre>
+ <script>
+ function showDetails() {
+ $('button').style.display="none";
+ $('details').style.display="block";
+ }
+ </script>
+ </div>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/atom.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/atom.jelly
new file mode 100644
index 0000000..9583c92
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/atom.jelly
@@ -0,0 +1,55 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Peter Hayes
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson"><!-- No whitespace before xml header: -->&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+ <st:contentType value="application/atom+xml;charset=UTF-8" />
+ <j:new var="h" className="hudson.Functions" /><!-- instead of JSP functions -->
+
+ <!-- ATOM. See http://atompub.org/rfc4287.html for the format -->
+ <feed xmlns="http://www.w3.org/2005/Atom">
+ <title>${title}</title>
+ <link rel="alternate" type="text/html" href="${rootURL}${url}"/>
+
+ <j:choose>
+ <j:when test="${empty(entries)}">
+ <updated>2001-01-01T00:00:00Z</updated>
+ </j:when>
+ <j:otherwise>
+ <updated>${h.xsDate(adapter.getEntryTimestamp(entries[0]))}</updated>
+ </j:otherwise>
+ </j:choose>
+ <author>
+ <name>Hudson Server</name>
+ </author>
+ <id>urn:uuid:903deee0-7bfa-11db-9fe1-0800200c9a66</id>
+
+ <j:forEach var="e" items="${entries}" >
+ <entry>
+ <title>${adapter.getEntryTitle(e)}</title>
+ <link rel="alternate" type="text/html" href="${rootURL}${h.encode(adapter.getEntryUrl(e))}"/>
+ <id>${adapter.getEntryID(e)}</id>
+ <published>${h.xsDate(adapter.getEntryTimestamp(e))}</published>
+ <updated>${h.xsDate(adapter.getEntryTimestamp(e))}</updated>
+ <j:set var="desc" value="${adapter.getEntryDescription(e)}"/>
+ <j:if test="${desc!=null}">
+ <content>${desc}</content>
+ </j:if>
+ </entry>
+ </j:forEach>
+ </feed>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/available.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/available.jelly
new file mode 100644
index 0000000..8548e42
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/available.jelly
@@ -0,0 +1,24 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ List of available new plugins
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <local:table page="available" list="${app.updateCenter.categorizedAvailables}" xmlns:local="/hudson/PluginManager" />
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/badge.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/badge.jelly
new file mode 100644
index 0000000..608d6c7
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/badge.jelly
@@ -0,0 +1,26 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:if test="${it.isTagged()}" xmlns:j="jelly:core">
+ <a href="${rootURL}/${it.build.url}tagBuild/">
+ <img width="16" height="16"
+ tooltip="${it.tooltip}"
+ alt="[tagged]"
+ src="${imagesURL}/16x16/save.png"/>
+ </a>
+</j:if>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/ballColorTd.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/ballColorTd.jelly
new file mode 100644
index 0000000..8a0b34b
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/ballColorTd.jelly
@@ -0,0 +1,34 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, CloudBees, Inc.
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Display the ball in a TD.
+ <st:attribute name="it" type="hudson.model.BallColor">
+ Color of the ball or null to skip drawing.
+ </st:attribute>
+ <st:attribute name="style">
+ Additional CSS styles to apply.
+ </st:attribute>
+ </st:documentation>
+ <td data="${it.ordinal()}">
+ <j:if test="${attrs.it!=null}">
+ <img src="${it.getImageOf(iconSize)}" alt="${it.description}"
+ tooltip="${it.description}" style="${attrs.style}" class="icon${iconSize}"/>
+ </j:if>
+ </td>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/bar.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/bar.jelly
new file mode 100644
index 0000000..3ba71a6
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/bar.jelly
@@ -0,0 +1,65 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Daniel Dyer, id:cactusman
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Show a long bar that shows how many tests have failed and succeeded.
+
+ Attributes
+ ==========
+
+ @it current test result
+ @prev previous test result
+
+ both objects need to have .failCount and .totalCount properties
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <div>
+ <j:choose>
+ <j:when test="${it.totalCount==0}">
+ ${%No tests}
+ </j:when>
+ <j:otherwise>
+ <div>
+ ${%failures(it.failCount)}
+ <j:if test="${prev!=null}">
+ (${h.getDiffString(it.failCount-prev.failCount)})
+ </j:if>
+ <!-- Only show skips if there are some since they don't make sense for JUnit, only for TestNG. -->
+ <j:if test="${it.skipCount > 0}">
+ , ${%skipped(it.skipCount)}
+ <j:if test="${prev!=null}">
+ (${h.getDiffString(it.skipCount-prev.skipCount)})
+ </j:if>
+ </j:if>
+ </div>
+ <div style="width:100%; height:1em; background-color: #729FCF">
+ <!-- Failed tests part of the bar. -->
+ <div style="width:${it.failCount*100/it.totalCount}%; height: 1em; background-color: #EF2929; float: left"></div>
+ <!-- Skipped tests part of the bar. -->
+ <div style="width:${it.skipCount*100/it.totalCount}%; height: 1em; background-color: #FCE94F; float: left"></div>
+ </div>
+ <div align="right">
+ ${%tests(it.totalCount)}
+ <j:if test="${prev!=null}">
+ (${h.getDiffString(it.totalCount-prev.totalCount)})
+ </j:if>
+ </div>
+ </j:otherwise>
+ </j:choose>
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/block.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/block.jelly
new file mode 100644
index 0000000..b0d33b7
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/block.jelly
@@ -0,0 +1,28 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Full-width space in the form table that can be filled with arbitrary HTML.
+ </st:documentation>
+ <tr>
+ <td colspan="3">
+ <d:invokeBody />
+ </td>
+ </tr>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/body.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/body.jelly
new file mode 100644
index 0000000..4a5c1ae
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/body.jelly
@@ -0,0 +1,121 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi,
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+
+ <script type="text/javascript">
+ <!-- TODO make sure load doesn't happen every time -->
+ function showStackTrace(id,query) {
+ var element = document.getElementById(id)
+ element.style.display = "";
+ document.getElementById(id + "-showlink").style.display = "none";
+ document.getElementById(id + "-hidelink").style.display = "";
+
+ var rqo = new XMLHttpRequest();
+ rqo.open('GET', query, true);
+ rqo.onreadystatechange = function() { element.innerHTML = rqo.responseText; }
+ rqo.send(null);
+ }
+
+ function hideStackTrace(id) {
+ document.getElementById(id).style.display = "none";
+ document.getElementById(id + "-showlink").style.display = "";
+ document.getElementById(id + "-hidelink").style.display = "none";
+ }
+ </script>
+
+ <j:if test="${it.failCount!=0}">
+ <h2>${%All Failed Tests}</h2>
+ <table class="pane sortable">
+ <tr>
+ <td class="pane-header">${%Test Name}</td>
+ <td class="pane-header" style="width:4em">${%Duration}</td>
+ <td class="pane-header" style="width:3em">${%Age}</td>
+ </tr>
+ <j:forEach var="f" items="${it.failedTests}" varStatus="i">
+ <tr>
+ <td class="pane">
+ <a id="test-${f.fullName}-showlink"
+ href="javascript:showStackTrace('test-${h.jsStringEscape(f.fullName)}','${f.getRelativePathFrom(it)}/summary')">&gt;&gt;&gt;</a>
+ <a id="test-${f.fullName}-hidelink" style="display:none"
+ href="javascript:hideStackTrace('test-${h.jsStringEscape(f.fullName)}')">&lt;&lt;&lt;</a>
+ <st:nbsp/>
+ <a href="${f.getRelativePathFrom(it)}"><st:out value="${f.fullName}"/></a>
+ <st:nbsp/>
+ <j:forEach var="badge" items="${f.testActions}">
+ <st:include it="${badge}" page="badge.jelly" optional="true"/>
+ </j:forEach>
+ <div id="test-${f.fullName}" class="hidden" style="display:none">
+ ${%Loading...}
+ </div>
+ </td>
+
+ <td class="pane" style="text-align:right;">
+ ${f.duration}
+ </td>
+ <td class="pane" style="text-align:right;">
+ <a href="${rootURL}/${f.failedSinceRun.url}">${f.age}</a>
+ </td>
+ </tr>
+ </j:forEach>
+ </table>
+ </j:if>
+
+ <j:if test="${it.totalCount!=0}">
+ <h2>${%All Tests}</h2>
+ <table class="pane sortable" id="testresult">
+ <tr>
+ <td class="pane-header">${it.childTitle}</td>
+ <td class="pane-header" style="width:5em">${%Duration}</td>
+ <td class="pane-header" style="width:5em">${%Fail}</td>
+ <td class="pane-header" style="width:1em; font-size:smaller; white-space:nowrap;">(${%diff})</td>
+ <td class="pane-header" style="width:5em">${%Skip}</td>
+ <td class="pane-header" style="width:1em; font-size:smaller; white-space:nowrap;">(${%diff})</td>
+ <td class="pane-header" style="width:5em">${%Total}</td>
+ <td class="pane-header" style="width:1em; font-size:smaller; white-space:nowrap;">(${%diff})</td>
+ </tr>
+ <tbody>
+ <j:forEach var="p" items="${it.children}">
+ <j:set var="prev" value="${p.previousResult}" />
+ <tr>
+ <td class="pane">
+ <a href="${p.safeName}/"><span style="${prev==null?'font-weight:bold':''}"><st:out value="${p.name}" /></span></a>
+ <st:nbsp/>
+ <j:forEach var="badge" items="${p.testActions}">
+ <st:include it="${badge}" page="badge.jelly" optional="true"/>
+ </j:forEach>
+ </td>
+ <td class="pane" style="text-align:right" data="${p.duration}">${p.durationString}</td>
+ <td class="pane" style="text-align:right">${p.failCount}</td>
+ <td class="pane" style="text-align:right">
+ ${h.getDiffString2(p.failCount-prev.failCount)}
+ </td>
+ <td class="pane" style="text-align:right">${p.skipCount}</td>
+ <td class="pane" style="text-align:right">
+ ${h.getDiffString2(p.skipCount-prev.skipCount)}
+ </td>
+ <td class="pane" style="text-align:right">${p.totalCount}</td>
+ <td class="pane" style="text-align:right">
+ ${h.getDiffString2(p.totalCount-prev.totalCount)}
+ </td>
+ </tr>
+ </j:forEach>
+ </tbody>
+ </table>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/booleanRadio.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/booleanRadio.jelly
new file mode 100644
index 0000000..59c4e87
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/booleanRadio.jelly
@@ -0,0 +1,39 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010, CollabNet
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define"
+ xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Binds a boolean field to two radio buttons that say Yes/No OK/Cancel Top/Bottom.
+
+ <st:attribute name="field">
+ Databinding field.
+ </st:attribute>
+ <st:attribute name="true">
+ Text to be displayed for the 'true' value. Defaults to 'Yes'.
+ </st:attribute>
+ <st:attribute name="false">
+ Text to be displayed for the 'false' value. Defaults to 'No'.
+ </st:attribute>
+ </st:documentation>
+ <f:prepareDatabinding />
+
+ <f:radio name="_.${attrs.field}" value="true" checked="${instance[field]}" />
+ <label class="attach-previous">${attrs['true']?:'%Yes'}</label>
+ <f:radio name="_.${attrs.field}" value="false" checked="${!instance[field]}" />
+ <label class="attach-previous">${attrs['false']?:'%No'}</label>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/build-permalink.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/build-permalink.jelly
new file mode 100644
index 0000000..bb1d4e5
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/build-permalink.jelly
@@ -0,0 +1,35 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Permalink to a build from a project page
+
+ @attrs property
+ The build property name
+ @attrs title
+ Title of the link
+-->
+ <!-- TODO: delete once batch-task plugin is updated. -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:p="/lib/hudson/project">
+ <j:set var="b" value="${it[property]}"/>
+ <j:if test="${b!=null}">
+ <li>
+ <a href="${property}/">${%format(title,b.number,b.timestampString)}</a>
+ </li>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/buildCaption.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/buildCaption.jelly
new file mode 100644
index 0000000..eb909e8
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/buildCaption.jelly
@@ -0,0 +1,43 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ displays a caption for build/externalRun.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <h1>
+ <j:if test="${it.building}">
+ <div style="float:right">
+ <table class="middle-align"><tr>
+ <td>
+ ${%Progress}:
+ </td><td>
+ <t:buildProgressBar build="${it}"/>
+ </td><td>
+ <j:if test="${it.parent.hasAbortPermission()}">
+ <a href="stop"><img src="${imagesURL}/16x16/stop.png" alt="[${%cancel}]" /></a>
+ </j:if>
+ </td>
+ </tr></table>
+ </div>
+ </j:if>
+
+ <img src="buildStatus" width="48" height="48" alt="${it.iconColor.description}" tooltip="${it.iconColor.description}" />
+ <d:invokeBody />
+ </h1>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/buildHealth.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/buildHealth.jelly
new file mode 100644
index 0000000..172b8c7
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/buildHealth.jelly
@@ -0,0 +1,67 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ <%@ attribute name="job" required="true" type="hudson.model.Job" %>
+ <%@ attribute name="iconSize" required="true" type="java.lang.String" %>
+ <%@ attribute name="td" required="false" type="java.lang.String" %>
+ <%@ attribute name="link" required="false" type="java.lang.String" %>
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:set var="buildHealth" value="${job.buildHealth}"/>
+ <j:if test="${td}"><j:set var="useTdElement" value="x"/></j:if>
+ <x:element name="${useTdElement!=null?'td':'div'}">
+ <x:attribute name="data">${buildHealth.score}</x:attribute>
+ <x:attribute name="class">healthReport</x:attribute>
+ <x:attribute name="onmouseover">this.className='healthReport hover';return true;
+ </x:attribute>
+ <x:attribute name="onmouseout">this.className='healthReport';return true;</x:attribute>
+ <j:if test="${buildHealth!=null}">
+ <a href="${empty(link)?'#':link}" style="${attrs.style}">
+ <img src="${rootURL}${buildHealth.getIconUrl(iconSize)}"
+ alt="${buildHealth.score}%"/>
+ </a>
+ </j:if>
+ <j:set var="healthReports" value="${job.buildHealthReports}"/>
+ <j:if test="${!empty(healthReports)}">
+ <div class="healthReportDetails">
+ <table border="0">
+ <thead>
+ <tr>
+ <th align="left">W</th>
+ <th align="left">${%Description}</th>
+ <th align="right">%</th>
+ </tr>
+ </thead>
+ <tbody>
+ <j:forEach var="rpt" items="${job.buildHealthReports}">
+ <tr>
+ <td align="left">
+ <img src="${rootURL}${rpt.getIconUrl('16x16')}" alt=""
+ title=""/>
+ </td>
+ <td>${rpt.localizableDescription}</td>
+ <td align="right">${rpt.score}</td>
+ </tr>
+ </j:forEach>
+ </tbody>
+ </table>
+ </div>
+ </j:if>
+ </x:element>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/buildLink.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/buildLink.jelly
new file mode 100644
index 0000000..389c455
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/buildLink.jelly
@@ -0,0 +1,49 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Link to a build. Used by fingerprint/index.jsp
+
+ Attributes:
+ jobName name of the job. Can be omitted if you don't want to show a name.
+ job A 'job' object. Can be omitted if you don't want to link.
+ number build number to link to.
+ href Link target. If missing, the top page of the build.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:set var="jobName_" value="${h.appendSpaceIfNotNull(jobName)}"/>
+ <j:choose>
+ <j:when test="${job==null}">
+ ${jobName_}#<!-- -->${number}
+ </j:when>
+ <j:otherwise>
+ <j:set var="r" value="${job.getBuildByNumber(number)}" />
+ <j:choose>
+ <j:when test="${r==null}">
+ <a href="${rootURL}/${job.url}">${jobName}</a>
+ #<!-- -->${number}
+ </j:when>
+ <j:otherwise>
+ <a href="${attrs.href ?: rootURL+'/'+r.url}">
+ <img src="${imagesURL}/16x16/${r.buildStatusUrl}"
+ alt="${r.iconColor.description}"/>${jobName_}#<!-- -->${number}</a>
+ </j:otherwise>
+ </j:choose>
+ </j:otherwise>
+ </j:choose>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/buildListTable.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/buildListTable.jelly
new file mode 100644
index 0000000..5e8cb60
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/buildListTable.jelly
@@ -0,0 +1,68 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <st:documentation>
+ Creates a table of builds.
+ <st:attribute name="builds" use="required">
+ A collection of builds to be displayed.
+ </st:attribute>
+ <st:attribute name="jobBaseUrl" use="required">
+ The base URL of all job/build links. Normally ${rootURL}/
+ </st:attribute>
+ </st:documentation>
+
+ <t:setIconSize/>
+ <table class="sortable pane bigtable" id="projectStatus">
+ <tr>
+ <th><st:nbsp/></th>
+ <th>${%Build}</th>
+ <th initialSortDir="up">${%Date}</th>
+ <th>${%Status}</th>
+ <th><st:nbsp/></th>
+ </tr>
+ <!-- TODO: support gradual expansion of the list -->
+ <j:forEach var="b" items="${h.subList(attrs.builds,50)}">
+ <tr>
+ <td data="${b.iconColor.ordinal()}">
+ <a href="${jobBaseUrl}${b.url}">
+ <img src="${imagesURL}/${iconSize}/${b.buildStatusUrl}"
+ alt="${b.iconColor.description}"/>
+ </a>
+ </td>
+ <td>
+ <a href="${jobBaseUrl}${b.parent.url}">${b.parent.fullDisplayName}</a>
+ <st:nbsp/>
+ <a href="${jobBaseUrl}${b.url}">${b.displayName}</a>
+ </td>
+ <td data="${b.timestampString2}">
+ ${b.timestampString}
+ </td>
+ <td>
+ <t:buildStatusSummary build="${b}" />
+ </td>
+ <td>
+ <a href="${jobBaseUrl}${b.url}console">
+ <img src="${imagesURL}/${subIconSize}/terminal.png" title="${%Console output}" alt="${%Console output}" border="0" />
+ </a>
+ </td>
+ </tr>
+ </j:forEach>
+ </table>
+ <t:rssBar-with-iconSize/>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/buildProgressBar.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/buildProgressBar.jelly
new file mode 100644
index 0000000..b606608
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/buildProgressBar.jelly
@@ -0,0 +1,33 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Progress bar for a build in progress.
+
+ <st:attribute name="build" use="required" type="hudson.model.Queue.Executable">
+ Build in progress.
+ </st:attribute>
+ <st:attribute name="executor">
+ Executor that's carrying out the build. If null, defaults to "build.executor"
+ </st:attribute>
+ </st:documentation>
+ <j:set var="executor" value="${executor?:build.executor}" />
+ <t:progressBar tooltip="${%text(executor.timestampString,executor.estimatedRemainingTime)}"
+ red="${executor.isLikelyStuck()}"
+ pos="${executor.progress}" href="${rootURL}/${build.url}console"/>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/buildRangeLink.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/buildRangeLink.jelly
new file mode 100644
index 0000000..2074363
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/buildRangeLink.jelly
@@ -0,0 +1,43 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Link to a range of build. Used by fingerprint/index.jsp
+
+ <%@ attribute name="range" type="java.lang.Object" required="true" %>
+ <%@ attribute name="job" type="hudson.model.Job" required="true" %>
+-->
+<!-- it's hudson.model.Fingerprint.RangeSet but Tomcat can't seem to handler inner classes -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:forEach var="r" items="${range.ranges}">
+ <j:choose>
+ <j:when test="${r.start==r.end-1}">
+ <t:buildLink job="${job}" number="${r.start}" />
+ </j:when>
+ <j:when test="${r.start==r.end-2}">
+ <t:buildLink job="${job}" number="${r.start}" />
+ <st:nbsp/>
+ <t:buildLink job="${job}" number="${r.end-1}" />
+ </j:when>
+ <j:otherwise>
+ <t:buildLink job="${job}" number="${r.start}" />-<t:buildLink job="${job}" number="${r.end-1}" />
+ </j:otherwise>
+ </j:choose>
+ <st:nbsp/>
+ </j:forEach>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/buildStatusSummary.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/buildStatusSummary.jelly
new file mode 100644
index 0000000..4e249cd
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/buildStatusSummary.jelly
@@ -0,0 +1,29 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Simon Wiest
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core">
+ <j:set var="summary" value="${build.buildStatusSummary}"/>
+ <j:choose>
+ <j:when test="${summary.isWorse}">
+ <font color='red'><j:out value="${app.markupFormatter.translate(summary.message)}"/></font>
+ </j:when>
+ <j:otherwise>
+ <j:out value="${app.markupFormatter.translate(summary.message)}"/>
+ </j:otherwise>
+ </j:choose>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/buildTimeTrend.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/buildTimeTrend.jelly
new file mode 100644
index 0000000..17390ec
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/buildTimeTrend.jelly
@@ -0,0 +1,75 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi,
+#
+#
+#************************************************************************** -->
+
+
+<!-- Displays the chart that show how long builds are taking -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="${%title(it.displayName)}">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <h1>${%Timeline}</h1>
+ <st:include page="control.jelly" it="${it.timeline}" />
+ <div style="height:2em"/><!-- spacer -->
+
+ <h1>${%Build Time Trend}</h1>
+ <j:choose>
+ <j:when test="${it.builds.size()&gt;1}">
+ <div align="center">
+ <img src="buildTimeGraph/png" width="500" height="400" lazymap="buildTimeGraph/map" alt="[Build time graph]" style="float:right"/>
+ </div>
+
+ <j:set var="isMasterSlaveEnabled" value="${!empty(app.slaves)}"/>
+ <div align="center">
+ <table class="sortable" style="margin-top:1em;">
+ <tr>
+ <th><st:nbsp/></th>
+ <th initialSortDir="up">${%Build}</th>
+ <th>${%Duration}</th>
+ <j:if test="${isMasterSlaveEnabled}">
+ <th>${%Slave}</th>
+ </j:if>
+ </tr>
+ <j:forEach var="r" items="${it.builds}">
+ <tr>
+ <td>
+ <img width="16" height="16" src="${imagesURL}/16x16/${r.buildStatusUrl}" alt="${r.iconColor.description}" />
+ </td>
+ <td data="${r.number}">
+ <a href="${r.number}">
+ ${r.displayName}
+ </a>
+ </td>
+ <td data="${r.duration}">
+ ${r.durationString}
+ </td>
+ <j:if test="${isMasterSlaveEnabled}">
+ <td>
+ <t:node value="${r.builtOn}"/>
+ </td>
+ </j:if>
+ </tr>
+ </j:forEach>
+ </table>
+ </div>
+ </j:when>
+ <j:otherwise>
+ ${%More than 1 builds are needed for the trend report.}
+ </j:otherwise>
+ </j:choose>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/builds.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/builds.jelly
new file mode 100644
index 0000000..1fb2010
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/builds.jelly
@@ -0,0 +1,38 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, id:cactusman,
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="${it.displayName}">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <h1>
+ <img src="${imagesURL}/48x48/notepad.png" alt=""/>
+ ${%buildHistory(it.class.name=='hudson.model.AllView' ? app.displayName : it.displayName)}
+ </h1>
+
+ <st:include page="control.jelly" it="${it.timeline}" />
+ <div style="height:2em"/><!-- spacer -->
+
+ <div>
+ <a href="cc.xml">${%Export as plain XML}</a>
+ </div>
+ <!-- set @jobBaseUrl="" so that links to jobs will be under this view. -->
+ <t:buildListTable builds="${it.builds}" jobBaseUrl="" />
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/cascadingDescriptorList.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/cascadingDescriptorList.jelly
new file mode 100644
index 0000000..24ff6f2
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/cascadingDescriptorList.jelly
@@ -0,0 +1,56 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Nikita Levyankov
+#
+#
+#************************************************************************** -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:f="/lib/form">
+ <st:documentation>
+ Generates config pages from a list of Descriptors into a section. Tag is based on cascading functionality.
+ <st:attribute name="title">
+ Human readable title of the section to be rendered in HTML.
+ </st:attribute>
+ <st:attribute name="descriptors" use="required">
+ hudson.model.Descriptor collection whose configuration page is rendered.
+ </st:attribute>
+ <st:attribute name="projectPropertyClass">
+ ProjectProperty class that will be used for creating project property instance
+ based on hudson.util.CascadingUtil.getProjectProperty method. Default value is
+ org.eclipse.hudson.model.project.property.ExternalProjectProperty.class.
+ </st:attribute>
+ </st:documentation>
+
+ <j:set var="targetType" value="${it.class}"/>
+ <j:if test="${attrs.projectPropertyClass==null}">
+ <j:set var="attrs.projectPropertyClass"
+ value="${org.eclipse.hudson.model.project.property.ExternalProjectProperty.class}"/>
+ </j:if>
+ <j:if test="${!empty(descriptors) or context['org.apache.commons.jelly.body']!=null}">
+ <f:section title="${attrs.title}" name="${attrs.name}">
+ <d:invokeBody/>
+ <j:forEach var="descriptor" items="${descriptors}">
+ <j:set var="instanceProperty"
+ value="${cu.getProjectProperty(it, descriptor.jsonSafeClassName, attrs.projectPropertyClass)}"/>
+ <j:set var="instance" value="${instanceProperty.getValue()}"/>
+ <f:optionalBlock name="${descriptor.jsonSafeClassName}" help="${descriptor.helpFile}"
+ title="${descriptor.displayName}" checked="${instance!=null}"
+ resetUrl="${jobUrl}/resetProjectProperty?propertyName=${descriptor.jsonSafeClassName}"
+ isPropertyOverridden="${instanceProperty.isOverridden()}">
+ <st:include from="${descriptor}" page="${descriptor.configPage}" optional="true"/>
+ </f:optionalBlock>
+ <tr class="descriptor-separator"><td colspan="4"/></tr>
+ </j:forEach>
+ </f:section>
+ </j:if>
+</j:jelly>
+
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/cause.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/cause.jelly
new file mode 100644
index 0000000..2b82ce6
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/cause.jelly
@@ -0,0 +1,21 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Alan Harder
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <p class="error">${it} <a href="log">${%See log for more details}</a></p>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/causeOfDeath.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/causeOfDeath.jelly
new file mode 100644
index 0000000..55a338a
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/causeOfDeath.jelly
@@ -0,0 +1,51 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="${it.name}">
+ <l:header />
+ <l:side-panel>
+ <l:tasks>
+ <l:task icon="images/24x24/up.png" href="../.." title="${%Back}" />
+ </l:tasks>
+ </l:side-panel>
+ <l:main-panel>
+ <j:choose>
+ <j:when test="${it.alive}">
+ <h1>
+ <img src="${imagesURL}/48x48/blue.png" width="48" height="48" alt=""/>
+ ${%Thread is still alive}
+ </h1>
+ </j:when>
+ <j:otherwise>
+ <h1>
+ <img src="${imagesURL}/48x48/red.png" width="48" height="48" alt=""/>
+ ${%Thread has died}
+ </h1>
+ <pre>${h.printThrowable(it.causeOfDeath)}</pre>
+ <pre>
+ <a href="http://wiki.hudson-ci.org/display/HUDSON/Dead+Executor">${%more info}</a>
+ </pre>
+ <form method="post" action="yank" name="yank">
+ <f:submit value="${%Restart this thread}"/>
+ </form>
+ </j:otherwise>
+ </j:choose>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/cc.xml.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/cc.xml.jelly
new file mode 100644
index 0000000..ca87af9
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/cc.xml.jelly
@@ -0,0 +1,41 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Generate status XML compatible with CruiseControl.
+ See http://confluence.public.thoughtworks.org/display/CI/Multiple+Project+Summary+Reporting+Standard
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <st:contentType value="text/xml;charset=UTF-8" />
+ <j:new var="h" className="hudson.Functions" />
+
+ <Projects>
+ <j:forEach var="p" items="${it.items}">
+ <j:set var="lb" value="${p.lastCompletedBuild}"/>
+ <j:if test="${lb!=null}">
+ <Project name="${p.displayName}"
+ activity="${p.isBuilding() ? 'Building' : 'Sleeping'}"
+ lastBuildStatus="${h.toCCStatus(p)}"
+ lastBuildLabel="${lb.number}"
+ lastBuildTime="${lb.timestampString2}"
+ webUrl="${app.rootUrl}${p.url}"
+ />
+ </j:if>
+ </j:forEach>
+ </Projects>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/changes.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/changes.jelly
new file mode 100644
index 0000000..d1db49d
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/changes.jelly
@@ -0,0 +1,39 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Eric Lefevre-Ardant, id:cactusman
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Displays the console output
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="${%changes.title(it.name)}">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <j:set var="from" value="${request.getParameter('from')}"/>
+ <j:set var="to" value="${request.getParameter('to')}"/>
+ <j:set var="browser" value="${it.scm.effectiveBrowser}"/>
+
+ <h1>
+ ${%Changes}
+ <j:if test="${from!=null}">${%from.label(from)}</j:if>
+ <j:if test="${to!=null}">&#160;${%to.label(to)}</j:if>
+ </h1>
+ <j:set var="builds" value="${h.filter(it.buildsAsMap,from,to).values()}" />
+ <st:include it="${it.scm}" page="project-changes.jelly" />
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/checkUpdates.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/checkUpdates.jelly
new file mode 100644
index 0000000..6135281
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/checkUpdates.jelly
@@ -0,0 +1,43 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Forcibly check updates
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+<l:layout title="Update Center" permission="${app.ADMINISTER}" forcedUpdateCheck="true" norefresh="true">
+ <st:include page="sidepanel.jelly"/>
+ <l:main-panel>
+ <table style="width:100%; height:100%;">
+ <tr>
+ <td style="vertical-align: middle; text-align:center">
+ <h3>${%Checking Updates...} <span id="completionMarker" /></h3>
+ <a href=".">${%Go back to update center}</a>
+ </td>
+ </tr>
+ </table>
+ <script>
+ downloadService.siteCount = 0${app.updateCenter.sites.size()};
+ downloadService.completionHandler = function() {
+ if (--downloadService.siteCount &lt;= 0)
+ $$('completionMarker').innerHTML = "${%Done}";
+ }
+ </script>
+ </l:main-panel>
+</l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/checkbox.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/checkbox.jelly
new file mode 100644
index 0000000..f0d40be
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/checkbox.jelly
@@ -0,0 +1,61 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ &lt;input type="checkbox"> tag that takes true/false for @checked, which is more Jelly friendly.
+
+ <st:attribute name="name" />
+ <st:attribute name="checked" />
+ <st:attribute name="value" />
+ <st:attribute name="json">
+ Normally, the submitted JSON will be boolean indicating whether the checkbox was checked or not.
+ This is sometimes inconvenient if you have a UI that lets user select a subset of a set.
+ If this attribute is present, the submitted JSON will have this as a string value if the checkbox is checked,
+ and none otherwise, making the subset selection easier.
+ </st:attribute>
+ <st:attribute name="default">
+ The default value of the check box, in case both @checked and @instance are null.
+ If this attribute is unspecified or null, it defaults to unchecked, otherwise checked.
+ </st:attribute>
+ <st:attribute name="id" />
+ <st:attribute name="onclick" />
+ <st:attribute name="class" />
+ <st:attribute name="negative" />
+ <st:attribute name="field">
+ Used for databinding. TBD.
+ </st:attribute>
+ <st:attribute name="title">
+ If specified, this human readable text will follow the checkbox, and clicking this text also
+ toggles the checkbox.
+ </st:attribute>
+ </st:documentation>
+ <f:prepareDatabinding />
+ <input type="checkbox"
+ name="${attrs.name?:'_.'+attrs.field}"
+ value="${attrs.value}"
+ onclick="${attrs.onclick}" id="${attrs.id}" class="${attrs.negative!=null ? 'negative' : null} ${attrs.checkUrl!=null?'validated':''}"
+ checkUrl="${attrs.checkUrl}" json="${attrs.json}"
+ checked="${(attrs.checked ?: instance[attrs.field] ?: attrs.default) ? 'true' : null}"/>
+ <j:if test="${attrs.title!=null}">
+ <label class="attach-previous">
+ <j:whitespace> </j:whitespace>
+ ${attrs.title}
+ </label>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/column.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/column.jelly
new file mode 100644
index 0000000..bacba23
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/column.jelly
@@ -0,0 +1,22 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Martin Eigenbrodt
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <t:buildHealth td="true" style="${indenter.getRelativeShift(job)}"
+ link="${jobBaseUrl}${job.shortUrl}lastBuild"/>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/columnHeader.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/columnHeader.jelly
new file mode 100644
index 0000000..f74b679
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/columnHeader.jelly
@@ -0,0 +1,21 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Martin Eigenbrodt
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+ <j:jelly xmlns:j="jelly:core">
+ <th tooltip="${%Weather report showing aggregated status of recent builds}"><j:out value="${h.nbspIndent(iconSize)}"/>W</th>
+ </j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/combobox.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/combobox.jelly
new file mode 100644
index 0000000..209b13a
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/combobox.jelly
@@ -0,0 +1,47 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Bruce Chapman, Alan Harder
+#
+#
+#************************************************************************** -->
+
+
+<!-- Tomcat doesn't like us using the attribute called 'class' -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Editable drop-down combo box that supports the data binding and AJAX updates.
+ Your descriptor should have the 'doFillXyzItems' method, which returns a ComboBoxModel
+ representation of the items in your combo box, and your instance field should
+ hold the current value.
+
+ <st:attribute name="clazz">
+ Additional CSS classes that the control gets.
+ </st:attribute>
+ <st:attribute name="field">
+ Used for databinding.
+ </st:attribute>
+ </st:documentation>
+
+ <st:once>
+ <script type="text/javascript" src="${request.contextPath}/scripts/utilities.js"/>
+ <script type="text/javascript" src="${request.contextPath}/scripts/combobox.js"/>
+ </st:once>
+
+ <f:prepareDatabinding/>
+ ${descriptor.calcFillSettings(field,attrs)} <!-- this figures out the 'fillUrl' and 'fillDependsOn' attribute -->
+
+ <m:input xmlns:m="jelly:hudson.util.jelly.MorphTagLibrary" ATTRIBUTES="${attrs}" EXCEPT="field items clazz"
+ autocomplete="off" class="combobox2 settings-input ${attrs.clazz}${attrs.checkUrl!=null ? ' validated' : ''}"
+ name="${attrs.name ?: '_.'+attrs.field}"
+ value="${attrs.value ?: instance[attrs.field]}" />
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config-blockWhenDownstreamBuilding.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config-blockWhenDownstreamBuilding.jelly
new file mode 100644
index 0000000..cf639d8
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config-blockWhenDownstreamBuilding.jelly
@@ -0,0 +1,30 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Shinod, Nikita Levyankov, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+
+<!-- Block build when downstream dependency is building -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:set var="blockBuildWhenDownstreamBuildingProperty"
+ value="${cu.getBooleanProjectProperty(it, it.BLOCK_BUILD_WHEN_DOWNSTREAM_BUILDING_PROPERTY_NAME)}"/>
+ <j:set var="blockBuildWhenDownstreamBuilding" value="${blockBuildWhenDownstreamBuildingProperty.getValue()}"/>
+ <f:optionalBlock name="blockBuildWhenDownstreamBuilding"
+ title="${%Block build when downstream project is building}"
+ help="/help/project-config/block-downstream-building.html"
+ checked="${blockBuildWhenDownstreamBuilding}"
+ resetUrl="${jobUrl}/resetProjectProperty?propertyName=${it.BLOCK_BUILD_WHEN_DOWNSTREAM_BUILDING_PROPERTY_NAME}"
+ isPropertyOverridden="${blockBuildWhenDownstreamBuildingProperty.isOverridden()}"/>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config-blockWhenUpstreamBuilding.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config-blockWhenUpstreamBuilding.jelly
new file mode 100644
index 0000000..4b4a217
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config-blockWhenUpstreamBuilding.jelly
@@ -0,0 +1,31 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Shinod, Nikita Levyankov, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+
+<!-- Block build when upstream dependency is building -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:set var="blockBuildWhenUpstreamBuildingProperty"
+ value="${cu.getBooleanProjectProperty(it, it.BLOCK_BUILD_WHEN_UPSTREAM_BUILDING_PROPERTY_NAME)}"/>
+ <j:set var="blockBuildWhenUpstreamBuilding" value="${blockBuildWhenUpstreamBuildingProperty.getValue()}"/>
+ <f:optionalBlock name="blockBuildWhenUpstreamBuilding"
+ title="${%Block build when upstream project is building}"
+ help="/help/project-config/block-upstream-building.html"
+ checked="${blockBuildWhenUpstreamBuilding}"
+ resetUrl="${jobUrl}/resetProjectProperty?propertyName=${it.BLOCK_BUILD_WHEN_UPSTREAM_BUILDING_PROPERTY_NAME}"
+ isPropertyOverridden="${blockBuildWhenUpstreamBuildingProperty.isOverridden()}"/>
+</j:jelly>
+
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config-buildWrappers.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config-buildWrappers.jelly
new file mode 100644
index 0000000..28c9574
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config-buildWrappers.jelly
@@ -0,0 +1,24 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Nikita Levyankov
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Build wrapper config pane
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:p="/lib/hudson/project">
+ <t:cascadingDescriptorList title="${%Build Environment}" descriptors="${h.getBuildWrapperDescriptors(it)}"/>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config-builders.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config-builders.jelly
new file mode 100644
index 0000000..27e800c
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config-builders.jelly
@@ -0,0 +1,36 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Nikita Levyankov
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Builder config pane
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:p="/lib/hudson/project">
+ <j:set var="buildersProperty" value="${cu.getDescribableListProjectProperty(it, it.BUILDERS_PROPERTY_NAME)}"/>
+ <j:set var="builders" value="${buildersProperty.getValue()}"/>
+ <!-- build config pane -->
+ <f:section title="${%Build}">
+ <f:block>
+ <f:hetero-list name="builder" hasHeader="true"
+ descriptors="${h.getBuilderDescriptors(it)}"
+ items="${builders}"
+ isPropertyOverridden="${buildersProperty.isOverridden()}"
+ resetUrl="${jobUrl}/resetProjectProperty?propertyName=${it.BUILDERS_PROPERTY_NAME}"
+ addCaption="${%Add build step}"/>
+ </f:block>
+ </f:section>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config-cleanWorkspace.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config-cleanWorkspace.jelly
new file mode 100644
index 0000000..82f30d0
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config-cleanWorkspace.jelly
@@ -0,0 +1,28 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Knute G. Axelson, Nikita Levyankov, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+
+<!-- clean workspace -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:set var="cleanWorkspaceRequiredProperty" value="${cu.getBooleanProjectProperty(it, it.CLEAN_WORKSPACE_REQUIRED_PROPERTY_NAME)}"/>
+ <j:set var="cleanWorkspaceRequired" value="${cleanWorkspaceRequiredProperty.getValue()}"/>
+ <f:optionalBlock name="cleanWorkspaceRequired" title="${%Clean workspace before build}"
+ checked="${cleanWorkspaceRequired}"
+ resetUrl="${jobUrl}/resetProjectProperty?propertyName=${it.CLEAN_WORKSPACE_REQUIRED_PROPERTY_NAME}"
+ isPropertyOverridden="${cleanWorkspaceRequiredProperty.isOverridden()}"
+ help="/help/project-config/cleanWorkspace.html" />
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config-customWorkspace.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config-customWorkspace.jelly
new file mode 100644
index 0000000..58f75b2
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config-customWorkspace.jelly
@@ -0,0 +1,31 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, id:cactusman, Nikita Levyankov, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+
+<!-- custom workspace -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:set var="customWorkspaceProperty" value="${cu.getStringProjectProperty(it, it.CUSTOM_WORKSPACE_PROPERTY_NAME)}"/>
+ <j:set var="customWorkspace" value="${customWorkspaceProperty.getValue()}"/>
+ <f:optionalBlock name="customWorkspace" title="${%Use custom workspace}" checked="${customWorkspace!=null}"
+ isPropertyOverridden="${customWorkspaceProperty.isOverridden()}"
+ resetUrl="${jobUrl}/resetProjectProperty?propertyName=${it.CUSTOM_WORKSPACE_PROPERTY_NAME}"
+ help="/help/project-config/custom-workspace.html">
+ <f:entry title="${%Directory}" isPropertyOverridden="${customWorkspaceProperty.isOverridden()}">
+ <f:textbox name="customWorkspace.directory" value="${customWorkspace}" />
+ </f:entry>
+ </f:optionalBlock>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config-disableBuild.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config-disableBuild.jelly
new file mode 100644
index 0000000..1b6021f
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config-disableBuild.jelly
@@ -0,0 +1,25 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Configuration entry for disabling builds
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <f:optionalBlock name="disable" title="${%Disable Build} (${%No new builds will be executed until the project is re-enabled.})" checked="${it.disabled}"
+ help="/help/project-config/disable.html" />
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config-publishers.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config-publishers.jelly
new file mode 100644
index 0000000..8713945
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config-publishers.jelly
@@ -0,0 +1,24 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Nikita Levyankov
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Publisher config pane
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:p="/lib/hudson/project">
+ <t:cascadingDescriptorList title="${%Post-build Actions}" descriptors="${h.getPublisherDescriptors(it)}"/>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config-quietPeriod.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config-quietPeriod.jelly
new file mode 100644
index 0000000..15cb630
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config-quietPeriod.jelly
@@ -0,0 +1,33 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, id:cactusman, Nikita Levyankov, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+
+<!-- custom quiet period -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:set var="quietPeriodProperty" value="${cu.getIntegerProjectProperty(it, it.QUIET_PERIOD_PROPERTY_NAME)}"/>
+ <j:set var="quietPeriod" value="${quietPeriodProperty.getValue()}"/>
+ <f:optionalBlock name="hasQuietPeriod" title="${%Quiet period}"
+ checked="${quietPeriod!=null and quietPeriod!=quietPeriodProperty.getDefaultValue()}"
+ isPropertyOverridden="${quietPeriodProperty.isOverridden()}"
+ resetUrl="${jobUrl}/resetProjectProperty?propertyName=${it.QUIET_PERIOD_PROPERTY_NAME}"
+ help="/help/project-config/quietPeriod.html">
+ <f:entry title="${%Quiet period}"
+ description="${%Number of seconds}" isPropertyOverridden="${quietPeriodProperty.isOverridden()}">
+ <f:textbox clazz="number" name="quiet_period" value="${quietPeriod}"/>
+ </f:entry>
+ </f:optionalBlock>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config-retryCount.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config-retryCount.jelly
new file mode 100644
index 0000000..4b5a60d
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config-retryCount.jelly
@@ -0,0 +1,32 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Shinod, Nikita Levyankov, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+
+<!-- custom retry count -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:set var="scmCheckoutRetryCountProperty" value="${cu.getIntegerProjectProperty(it, it.SCM_CHECKOUT_RETRY_COUNT_PROPERTY_NAME)}"/>
+ <j:set var="scmCheckoutRetryCount" value="${scmCheckoutRetryCountProperty.getValue()}"/>
+ <f:optionalBlock name="hasScmCheckoutRetryCount" title="${%Retry Count}"
+ checked="${scmCheckoutRetryCount!=null and scmCheckoutRetryCount!=scmCheckoutRetryCountProperty.getDefaultValue()}"
+ isPropertyOverridden="${scmCheckoutRetryCountProperty.isOverridden()}"
+ resetUrl="${jobUrl}/resetProjectProperty?propertyName=${it.SCM_CHECKOUT_RETRY_COUNT_PROPERTY_NAME}"
+ help="/help/project-config/scmCheckoutRetryCount.html">
+ <f:entry title="${%SCM checkout retry count}" isPropertyOverridden="${scmCheckoutRetryCountProperty.isOverridden()}">
+ <f:textbox name="scmCheckoutRetryCount" value="${scmCheckoutRetryCount}"/>
+ </f:entry>
+ </f:optionalBlock>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config-scm.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config-scm.jelly
new file mode 100644
index 0000000..d94fccf
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config-scm.jelly
@@ -0,0 +1,37 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+
+<!-- SCM config pane -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout"
+ xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:set var="scmProperty" value="${cu.getScmProjectProperty(it, it.SCM_PROPERTY_NAME)}"/>
+ <j:set var="scm" value="${scmProperty.getValue()}"/>
+
+ <f:section title="${%Source Code Management}" resetUrl="${scmProperty.isOverridden()?jobUrl+'/resetProjectProperty?propertyName='+it.SCM_PROPERTY_NAME :''}">
+ <j:set var="scms" value="${h.getSCMDescriptors(it)}"/>
+ <j:forEach var="idx" begin="0" end="${size(scms)-1}">
+ <j:set var="descriptor" value="${scms[idx]}"/>
+ <j:set var="scmd" value="${descriptor}"/> <!--Left for compatibility with listScmBrowsers.jelly tag -->
+ <f:radioBlock name="scm" value="${idx}" title="${descriptor.displayName}" checked="${it.scm.descriptor==descriptor}"
+ isPropertyOverridden="${scmProperty.isOverridden()}">
+ <j:set var="instance" value="${it.scm.descriptor==descriptor ? it.scm : null}"/>
+ <st:include from="${descriptor}" page="${descriptor.configPage}"/>
+ </f:radioBlock>
+ </j:forEach>
+ </f:section>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config-trigger.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config-trigger.jelly
new file mode 100644
index 0000000..26ef0ce
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config-trigger.jelly
@@ -0,0 +1,33 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Nikita Levyankov
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Configure build triggers
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <!-- build triggers config pane -->
+ <j:invokeStatic var="triggers" className="hudson.triggers.Trigger" method="for_">
+ <j:arg value="${it}" type="hudson.model.Item" />
+ </j:invokeStatic>
+ <t:cascadingDescriptorList title="${%Build Triggers}" descriptors="${triggers}"
+ propertyClass="${org.eclipse.hudson.model.project.property.TriggerProjectProperty.class}">
+ <d:invokeBody />
+ <!-- pseudo-trigger to configure URL to trigger builds remotely. -->
+ <st:include page="/hudson/model/BuildAuthorizationToken/config.jelly" />
+ </t:cascadingDescriptorList>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config-upstream-pseudo-trigger.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config-upstream-pseudo-trigger.jelly
new file mode 100644
index 0000000..bedc95d
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config-upstream-pseudo-trigger.jelly
@@ -0,0 +1,37 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Present the pseudo "upstream project trigger". Used inside <p:config-trigger>
+
+ "it" is assumed to be a Project object.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <!-- pseudo-trigger to list upstream projects. -->
+ <j:set var="up" value="${it.buildTriggerUpstreamProjects}" />
+ <f:optionalBlock name="pseudoUpstreamTrigger"
+ help="/help/project-config/upstream.html"
+ title="${%Build after other projects are built}"
+ checked="${!empty(up)}">
+ <f:entry title="${%Projects names}"
+ description="${%Multiple projects can be specified like 'abc, def'}">
+ <f:textbox name="upstreamProjects" value="${h.getProjectListString(up)}"
+ checkUrl="'descriptorByName/BuildTrigger/check?value='+encodeURIComponent(this.value)"/>
+ </f:entry>
+ </f:optionalBlock>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/config.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/config.jelly
new file mode 100644
index 0000000..f436c46
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/config.jelly
@@ -0,0 +1,20 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Jesse Glick
+#
+#
+#************************************************************************** -->
+
+
+<!-- Columns normally have nothing to configure. -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core"/>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/configure-advanced.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/configure-advanced.jelly
new file mode 100644
index 0000000..a4cd8da
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/configure-advanced.jelly
@@ -0,0 +1,24 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Additional entries in the advanced section.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:p="/lib/hudson/project">
+ <p:config-customWorkspace />
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/configure-common.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/configure-common.jelly
new file mode 100644
index 0000000..bc6e743
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/configure-common.jelly
@@ -0,0 +1,98 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Nikita Levyankov, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Parts of the configuration that applies to Project and MavenModuleSet.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout"
+ xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:p="/lib/hudson/project" xmlns:this="this">
+ <p:config-disableBuild/>
+
+ <j:set var="concurrentBuildProperty" value="${cu.getBooleanProperty(it, it.CONCURRENT_BUILD_PROPERTY_NAME)}"/>
+ <j:set var="concurrentBuild" value="${concurrentBuildProperty.getValue()}"/>
+
+ <j:if test="${app.CONCURRENT_BUILD}">
+ <f:optionalBlock field="concurrentBuild" title="${%title.concurrentbuilds}"
+ checked="${concurrentBuild}"
+ resetUrl="${jobUrl}/resetProjectProperty?propertyName=${it.CONCURRENT_BUILD_PROPERTY_NAME}"
+ isPropertyOverridden="${concurrentBuildProperty.isOverridden()}"/>
+ </j:if>
+ <j:set var="jdks" value="${app.JDKs}"/>
+ <j:if test="${jdks.size() gt 1}">
+ <!-- if there's only one JDK configured, always use that. -->
+ <f:entry title="JDK"
+ description="${%JDK to be used for this project}"
+ isPropertyOverridden="${cu.getStringProjectProperty(it, it.JDK_PROPERTY_NAME).isOverridden()}">
+ <select class="setting-input validated" name="jdk"
+ checkUrl="'${rootURL}/defaultJDKCheck?value='+this.value">
+ <option>${%default.value}</option>
+ <j:forEach var="inst" items="${jdks}">
+ <f:option selected="${inst.name==it.getJDKName()}" value="${inst.name}">${inst.name}</f:option>
+ </j:forEach>
+ </select>
+ </f:entry>
+ </j:if>
+
+ <!-- master/slave -->
+ <j:set var="nodeChooserProperty" value="${cu.getBaseProjectProperty(it, it.APPOINTED_NODE_PROPERTY_NAME)}"/>
+ <j:set var="isNodeOverridden" value="${nodeChooserProperty.isOverridden()}" />
+ <j:if test="${app.labels.size() gt 1 || app.clouds.size() gt 0 || (it.assignedLabel!=null and it.assignedLabel!=app.selfLabel)}">
+ <f:optionalBlock name="${it.APPOINTED_NODE_PROPERTY_NAME}" title="${%Restrict where this project can be run}"
+ checked="${it.assignedLabel!=null}"
+ isPropertyOverridden="${isNodeOverridden}"
+ resetUrl="${jobUrl}/resetProjectProperty?propertyName=${it.APPOINTED_NODE_PROPERTY_NAME}"
+ help="/help/project-config/slave.html">
+ <f:radioBlock name="${it.AFFINITY_CHO0SER_KEY}" value="${it.BASIC_KEY}" title="${%Node and label menu}"
+ checked="${!it.advancedAffinityChooser and it.assignedLabel!=null}"
+ isPropertyOverridden="${isNodeOverridden}">
+ <f:entry title="${%Node}" isPropertyOverridden="${isNodeOverridden}">
+ <select class="setting-input" name="${it.SLAVE_KEY}">
+ <j:forEach var="s" items="${app.labels}">
+ <j:if test="${s.isAssignable()}">
+ <f:option selected="${s==it.assignedLabel}" value="${s.name}">${s.name}
+ <j:if test="${!empty(s.description)}">(${s.description})</j:if>
+ </f:option>
+ </j:if>
+ </j:forEach>
+ </select>
+ </f:entry>
+ </f:radioBlock>
+ <f:radioBlock name="${it.AFFINITY_CHO0SER_KEY}" value="advanced" title="${%Advanced Node and Label expressions}"
+ checked="${it.advancedAffinityChooser and it.assignedLabel!=null}"
+ isPropertyOverridden="${isNodeOverridden}">
+ <f:entry title="${%Label Expression}" field="assignedLabelString"
+ isPropertyOverridden="${isNodeOverridden}">
+ <f:textbox/>
+ </f:entry>
+ </f:radioBlock>
+ </f:optionalBlock>
+ </j:if>
+
+ <f:section title="${%Advanced Project Options configure-common}">
+ <f:advanced>
+ <p:config-quietPeriod/>
+ <p:config-retryCount/>
+ <p:config-blockWhenUpstreamBuilding/>
+ <p:config-blockWhenDownstreamBuilding/>
+ <st:include page="configure-advanced.jelly" optional="true"/>
+ <p:config-cleanWorkspace/>
+ </f:advanced>
+ </f:section>
+
+ <this:configure-scm/>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/configure-entries.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/configure-entries.jelly
new file mode 100644
index 0000000..ce046f7
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/configure-entries.jelly
@@ -0,0 +1,84 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Config page
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout"
+ xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <f:entry title="${%Description}" help="/help/system-config/master-slave/description.html">
+ <f:textbox field="nodeDescription" />
+ </f:entry>
+
+ <f:entry title="${%# of executors}" field="numExecutors">
+ <f:textbox />
+ </f:entry>
+
+ <f:entry title="${%Remote FS root}" field="remoteFS">
+ <f:textbox />
+ </f:entry>
+
+ <f:entry title="${%Labels}" field="labelString">
+ <f:textbox />
+ </f:entry>
+
+ <f:slave-mode name="mode" node="${it}" />
+
+ <!-- TODO: should be packaged as a tag -->
+ <f:dropdownList name="slave.launcher" title="${%Launch method}"
+ help="${descriptor.getHelpFile('launcher')}">
+ <j:forEach var="d" items="${h.getComputerLauncherDescriptors()}">
+ <f:dropdownListBlock value="${d.clazz.name}" name="${d.displayName}"
+ selected="${it.launcher.descriptor==d}"
+ title="${d.displayName}">
+ <j:set var="descriptor" value="${d}"/>
+ <j:set var="instance"
+ value="${it.launcher.descriptor==d ? it.launcher : null}"/>
+ <f:invisibleEntry>
+ <input type="hidden" name="stapler-class" value="${d.clazz.name}" />
+ </f:invisibleEntry>
+ <st:include from="${d}" page="${d.configPage}" optional="true"/>
+ </f:dropdownListBlock>
+ </j:forEach>
+ </f:dropdownList>
+
+ <!-- pointless to show this if there's only one option, which is the default -->
+ <j:if test="${h.getRetentionStrategyDescriptors().size() gt 1}">
+ <f:dropdownList name="slave.retentionStrategy" title="${%Availability}"
+ help="/help/system-config/master-slave/availability.html">
+ <j:forEach var="d" items="${h.getRetentionStrategyDescriptors()}">
+ <j:if test="${d != null}">
+ <f:dropdownListBlock value="${d.clazz.name}" name="${d.displayName}"
+ selected="${it.retentionStrategy.descriptor==d}"
+ title="${d.displayName}">
+ <j:set var="descriptor" value="${d}"/>
+ <j:set var="instance"
+ value="${it.retentionStrategy.descriptor==d ? it.retentionStrategy : null}"/>
+ <tr><td>
+ <input type="hidden" name="stapler-class" value="${d.clazz.name}" />
+ </td></tr>
+ <st:include from="${d}" page="${d.configPage}" optional="true"/>
+ </f:dropdownListBlock>
+ </j:if>
+ </j:forEach>
+ </f:dropdownList>
+ </j:if>
+
+ <f:descriptorList title="${%Node Properties}" descriptors="${h.getNodePropertyDescriptors(descriptor.clazz)}" field="nodeProperties" />
+
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/configure.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/configure.jelly
new file mode 100644
index 0000000..770c374
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/configure.jelly
@@ -0,0 +1,53 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Tom Huybrechts
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Edit View Page
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout norefresh="true">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <!-- to make the form field binding work -->
+ <j:set var="instance" value="${it}" />
+ <j:set var="descriptor" value="${it.descriptor}" />
+
+ <f:form method="post" action="configSubmit" name="viewConfig">
+ <f:entry title="${%Name}">
+ <f:textbox name="name" value="${it.viewName}" />
+ </f:entry>
+ <f:entry title="${%Description}" help="/help/view-config/description.html">
+ <f:textarea name="description" field="description" />
+ </f:entry>
+ <f:entry title="${%Filter build queue}" help="/help/view-config/filter-queue.html">
+ <f:checkbox name="filterQueue" field="filterQueue"/>
+ </f:entry>
+ <f:entry title="${%Filter build executors}" help="/help/view-config/filter-executors.html">
+ <f:checkbox name="filterExecutors" field="filterExecutors"/>
+ </f:entry>
+
+ <!-- subtypes can put entries here. -->
+ <st:include page="configure-entries.jelly" optional="true" />
+
+ <f:block>
+ <f:submit value="OK" />
+ </f:block>
+ </f:form>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/configureExecutors.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/configureExecutors.jelly
new file mode 100644
index 0000000..d204cfd
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/configureExecutors.jelly
@@ -0,0 +1,41 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Stephen Connolly
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ This used to be where people configure executors before 1.271, so just in case people have bookmarked this page,
+ explain what happened.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+<l:layout title="This page has moved">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <h1>
+ <img src="${imagesURL}/48x48/error.png" alt=""/>
+ This page has moved
+ </h1>
+ <p>
+ Starting 1.271, slave configuration is split into individual configuration page per slave,
+ accessible from <a href="computer/">here</a>.
+ </p>
+ <ul>
+ <li>To configure existing slaves, click the above link, click their name, and then click the config link from the left</li>
+ <li>To add a new slave, click the above link, and click "add new slave"</li>
+ </ul>
+ </l:main-panel>
+</l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/confirm.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/confirm.jelly
new file mode 100644
index 0000000..9c5d015
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/confirm.jelly
@@ -0,0 +1,47 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <l:layout title="${%ZFS file system creation}">
+ <l:header />
+ <l:side-panel />
+ <l:main-panel>
+ <h1>${%ZFS file system creation}</h1>
+ <div>
+ ${%blurb}
+
+ <j:if test="${!it.isRoot()}">
+ <div class="warning">
+ ${%You will need the root password of the system to do this.}
+ </div>
+ </j:if>
+ <ol>
+ <li>${%Restart itself so that the migration can be done without worrying about concurrent data modifications}</li>
+ <li>${%create(it.prospectiveZfsFileSystemName)}</li>
+ <li>${%rename(app.rootDir)}</li>
+ <li>${%mount(app.rootDir)}</li>
+ <li>${%delete(app.rootDir)}</li>
+ </ol>
+
+ <form action="start" method="post">
+ <f:submit value="${%Start migration}" />
+ </form>
+ </div>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/confirmDelete.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/confirmDelete.jelly
new file mode 100644
index 0000000..09a1f91
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/confirmDelete.jelly
@@ -0,0 +1,36 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, id:cactusman
+#
+#
+#************************************************************************** -->
+
+
+<!-- Confirm deletion of the build/run -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="${it.fullDisplayName}" norefresh="true">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <j:set var="msg" value="${it.whyKeepLog}"/>
+ <j:if test="${msg!=null}">
+ <b>${%Warning}</b>: ${%cannotMsg(msg)}
+ </j:if>
+ <j:if test="${msg==null}">
+ <form method="post" action="doDelete">
+ ${%Are you sure about deleting the build?}
+ <f:submit value="${%Yes}" />
+ </form>
+ </j:if>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/console.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/console.jelly
new file mode 100644
index 0000000..103355b
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/console.jelly
@@ -0,0 +1,67 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Displays the console output
+-->
+<?jelly escape-by-default='true'?>
+<st:compress xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="${it.fullDisplayName} Console" norefresh="true">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <t:buildCaption>
+ ${%Console Output}
+ </t:buildCaption>
+ <l:rightspace>
+ <a href="consoleText">
+ <img src="${imagesURL}/24x24/document.png" alt="" />${%View as plain text}
+ </a>
+ </l:rightspace>
+ <j:set var="threshold" value="${h.getSystemProperty('hudson.consoleTailKB')?:'150'}" />
+ <!-- Show at most last 150KB (can override with system property) unless consoleFull is set -->
+ <j:set var="offset" value="${empty(consoleFull) ? it.logFile.length()-threshold*1024 : 0}" />
+ <j:choose>
+ <j:when test="${offset > 0}">
+ ${%skipSome(offset/1024,"consoleFull")}
+ </j:when>
+ <j:otherwise>
+ <j:set var="offset" value="${0}" />
+ </j:otherwise>
+ </j:choose>
+
+ <j:out value="${h.generateConsoleAnnotationScriptAndStylesheet()}"/>
+
+ <j:choose>
+ <!-- Do progressive console output -->
+ <j:when test="${it.isLogUpdated()}">
+ <pre id="out" />
+ <div id="spinner">
+ <img src="${imagesURL}/spinner.gif" alt="" />
+ </div>
+ <t:progressiveText href="logText/progressiveHtml" idref="out" spinner="spinner" startOffset="${offset}" />
+ </j:when>
+ <!-- output is completed now. -->
+ <j:otherwise>
+ <pre>
+ <st:getOutput var="output" />
+ <j:whitespace>${it.writeLogTo(offset,output)}</j:whitespace>
+ </pre>
+ </j:otherwise>
+ </j:choose>
+ </l:main-panel>
+ </l:layout>
+</st:compress>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/consoleFull.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/consoleFull.jelly
new file mode 100644
index 0000000..6adf4f1
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/consoleFull.jelly
@@ -0,0 +1,21 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Alan Harder
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<st:compress xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <j:set var="consoleFull" value="true" />
+ <st:include page="console.jelly" />
+</st:compress>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/control.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/control.jelly
new file mode 100644
index 0000000..96d0d84
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/control.jelly
@@ -0,0 +1,162 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Erik Ramfelt, Seiji Sogabe
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <st:documentation>
+ Show timeline trend image. It takes two builds
+ </st:documentation>
+
+ <script type="text/javascript">
+ var SimileAjax = {
+ Platform: {}
+ };
+ </script>
+
+ <script type="text/javascript">
+ var browserName=navigator.appName;
+ if (browserName=="Microsoft Internet Explorer"){
+ //load ie friendly stylesheet
+ document.write('<link rel="stylesheet" type="text/css" href="${resURL}/scripts/timeline_2.3.0/timeline_ajax/styles/graphics-ie6.css" />')
+ } else{
+ document.write('<link rel="stylesheet" type="text/css" href="${resURL}/scripts/timeline_2.3.0/timeline_ajax/styles/graphics.css" />')
+ }
+ </script>
+
+ <link rel="stylesheet" type="text/css" href="${resURL}/scripts/timeline_2.3.0/timeline_ajax/styles/graphics.css" />
+ <link rel="stylesheet" type="text/css" href="${resURL}/scripts/timeline_2.3.0/timeline_js/timeline-bundle.css" />
+
+ <script src="${resURL}/scripts/timeline_2.3.0/timeline_ajax/simile-ajax-bundle.js" type="text/javascript" />
+
+ <script type="text/javascript">
+
+ var Timeline = {};
+ Timeline.DateTime = SimileAjax.DateTime;
+ Timeline.urlPrefix ='${resURL}/scripts/timeline_2.3.0/timeline_js/';
+ Timeline.serverLocale = '${h.serverLocale.language}';
+ Timeline.clientLocale = '${h.clientLocale.language}';;
+
+ </script>
+
+ <script src="${resURL}/scripts/timeline_2.3.0/timeline_js/timeline-bundle.js" type="text/javascript" />
+
+ <script src="${resURL}/scripts/timeline_2.3.0/timeline_js/scripts/l10n/en/labellers.js" type="text/javascript" />
+ <script src="${resURL}/scripts/timeline_2.3.0/timeline_js/scripts/l10n/en/timeline.js" type="text/javascript" />
+
+
+ <j:invokeStatic var="tz" className="java.util.TimeZone" method="getDefault"/>
+ <div id="tl" class="timeline" />
+ <div id="status" />
+
+ <script type="text/javascript">
+
+ <![CDATA[
+ // Respect Daylight Saving Time on client side
+ var tz = ${it.getTimeZoneOffset()};
+
+ function onLoadEvent() {
+ var tl_el = document.getElementById("tl");
+ var eventSource1 = new Timeline.DefaultEventSource();
+ eventSource1.loaded = {};
+ var interval = 24*60*60*1000;
+ eventSource1.ensureVisible = function(band) {
+ // make sure all data are loaded for the portion visible in the band
+ // $('status').innerHTML = "min="+band.getMinDate()+" max="+band.getMaxDate();
+ var min = Math.floor(band.getMinDate().getTime()/interval);
+ var max = Math.ceil(band.getMaxDate().getTime()/interval);
+ for (var i=min; i<=max; i++) {
+ if (!this.loaded[i]) {
+ this.loaded[i] = true;
+ new Ajax.Request("timeline/data",{
+ method:"POST",
+ parameters: {min: i*interval, max:(i+1)*interval},
+ onSuccess: function(t) {
+ try {
+ eventSource1.loadJSON(eval('('+t.responseText+')'),'.');
+ } catch (e) {
+ alert(e);
+ }
+ }
+ });
+ }
+ }
+ };
+
+
+ var theme1 = Timeline.ClassicTheme.create();
+ // theme1.autoWidth = true; // Set the Timeline's "width" automatically.
+ // Set autoWidth on the Timeline's first band's theme,
+ // will affect all bands.
+ theme1.timeline_start = new Date(${it.firstBuild.timeInMillis-24*60*60*1000});
+ theme1.timeline_stop = new Date(${it.lastBuild.timeInMillis+24*60*60*1000});
+
+ var d = new Date(${it.lastBuild.timeInMillis});
+ var bandInfos = [
+ // the bar that shows outline
+ Timeline.createBandInfo({
+ width: "50px", // set to a minimum, autoWidth will then adjust
+ intervalUnit: Timeline.DateTime.DAY,
+ intervalPixels: 200,
+ eventSource: eventSource1,
+ timeZone: tz,
+ theme: theme1,
+ layout: 'overview' // original, overview, detailed
+ }),
+ // the main area
+ Timeline.createBandInfo({
+ width: "200px",
+ eventSource: eventSource1,
+ timeZone: tz,
+ theme: theme1,
+ intervalUnit: Timeline.DateTime.HOUR,
+ intervalPixels: 200
+ })
+ ];
+ bandInfos[0].highlight = true;
+ bandInfos[0].syncWith = 1;
+
+ // create the Timeline
+ var tl = Timeline.create(tl_el, bandInfos, Timeline.HORIZONTAL);
+
+ tl.getBand(0).addOnScrollListener(function(band) {
+ eventSource1.ensureVisible(band);
+ });
+
+ tl.layout(); // display the Timeline
+
+ // if resized, redo layout
+ var resizeTimerID = null;
+ window.addEventListener('resize',function() {
+ if (resizeTimerID == null) {
+ resizeTimerID = window.setTimeout(function() {
+ resizeTimerID = null;
+ tl.layout();
+ }, 500);
+ }
+ },false);
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent('onload', onLoadEvent);
+ }else if (window.addEventListener) {
+ window.addEventListener('load', onLoadEvent, false);
+ }else {
+ document.addEventListener('load', onLoadEvent, false);
+ }
+ ]]>
+
+ </script>
+
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/custom-jnlp.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/custom-jnlp.jelly
new file mode 100644
index 0000000..4c004ea
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/custom-jnlp.jelly
@@ -0,0 +1,30 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="${it.displayName}">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <h1>Tweak Launch Parameters</h1>
+ <p>
+ This page allows you to tweak the JVM parameters when launching JNLP slave agents.
+ <!-- TODO: work from home for the rest -->
+ </p>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/delete.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/delete.jelly
new file mode 100644
index 0000000..4b535de
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/delete.jelly
@@ -0,0 +1,35 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Nikita Levyankov
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core">
+
+ <script src="${resURL}/scripts/popup-dialog.js" type="text/javascript"/>
+
+ <a href="${user.url}/delete" onclick="onLinkClick('question'); return false;">
+ <img src="${imagesURL}/24x24/edit-delete.png" alt="Delete"/>
+ </a>
+
+ <div id="question" style="display:none; cursor: default">
+ <div>
+ <form method="post" action="${user.url}/doDelete" name="delete">
+ <h4>${%Are you sure about deleting the user from Hudson?}</h4>
+ <input type="submit" class="yes" value="${%Yes}"/>
+ <input type="button" class="no" value="${%No}"/>
+ </form>
+ </div>
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/deleteConfirmationPanel.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/deleteConfirmationPanel.jelly
new file mode 100644
index 0000000..1118ca3
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/deleteConfirmationPanel.jelly
@@ -0,0 +1,24 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Nikita Levyankov
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<div>
+ <form method="post" action="doDelete">
+ <h4>${%Are you sure about deleting the view?}</h4>
+ <input type="submit" class="yes" value="${%Yes}" />
+ <input type="button" class="no" value="${%No}" />
+ </form>
+</div>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/description.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/description.jelly
new file mode 100644
index 0000000..f12321e
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/description.jelly
@@ -0,0 +1,34 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Renders a row that shows description text below an input field.
+ <st:attribute name="isPropertyOverridden">
+ if present and true - value is overridden
+ </st:attribute>
+ </st:documentation>
+ <j:if test="${attrs.isPropertyOverridden==null}">
+ <j:set target="${attrs}" property="isPropertyOverridden" value="false"/>
+ </j:if>
+ <tr class="${attrs.isPropertyOverridden? 'modified': 'original'}">
+ <td colspan="2" class="setting-description"/>
+ <td class="setting-description">
+ <d:invokeBody />
+ </td>
+ </tr>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/descriptionForm.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/descriptionForm.jelly
new file mode 100644
index 0000000..c60ac70
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/descriptionForm.jelly
@@ -0,0 +1,34 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Eric Lefevre-Ardant
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Used by editableDescription.jelly for loading the edit form.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:f="/lib/form" xmlns:l="/lib/layout">
+ <j:if test="${it.class.name=='hudson.model.Hudson'}">
+ <j:set var="it" value="${it.primaryView}"/>
+ </j:if>
+ <l:ajax>
+ <form action="submitDescription" method="post">
+ <f:textarea name="description" value="${it.description}" />
+ <div align="right">
+ <f:submit value="${%Submit}" />
+ </div>
+ </form>
+ </l:ajax>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/descriptorList.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/descriptorList.jelly
new file mode 100644
index 0000000..d32ec99
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/descriptorList.jelly
@@ -0,0 +1,79 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Generate config pages from a list of Descriptors into a section.
+
+ <st:attribute name="title">
+ Human readable title of the section to be rendered in HTML.
+ </st:attribute>
+ <st:attribute name="descriptors" use="required">
+ hudson.model.Descriptor collection whose configuration page is rendered.
+ </st:attribute>
+ <st:attribute name="instances">
+ Map&lt;Descriptor,Describable> that defines current instances of those descriptors.
+ These are used to fill initial values. Other classes that define the get(Descriptor)
+ method works fine, too, such as DescribableList.
+ </st:attribute>
+ <st:attribute name="field">
+ Either @field or @instances are required (or @field needs to be inherited from the ancestor &lt;entry> elemetn.
+ If field is specified, instances are assumed to be instance[field].
+
+ When this attribute is specified, JSON structure is properly set up so that the databinding
+ can set the field (or pass this collection as a constructor parameter of the same name.
+
+ This is more modern way of doing databinding, and thus preferred approach.
+ </st:attribute>
+ <st:attribute name="targetType">
+ the type for which descriptors will be configured.
+ default to ${it.class}
+ </st:attribute>
+ </st:documentation>
+
+ <j:if test="${attrs.field==null}">
+ <!-- inherit @field if we should do so -->
+ <j:set target="${attrs}" property="field" value="${entry.field}" />
+ </j:if>
+
+ <j:set var="targetType" value="${attrs.targetType ?: it.class}"/>
+ <j:set var="instances" value="${attrs.instances ?: instance[field] ?: descriptor['default'+h.capitalize(field)]}"/>
+
+ <j:if test="${!empty(descriptors) or context['org.apache.commons.jelly.body']!=null}">
+ <f:section title="${attrs.title}" name="${attrs.field?:attrs.name}">
+ <j:if test="${attrs.field!=null}">
+ <tr>
+ <td>
+ <input type="hidden" name="stapler-class-bag" value="true" />
+ </td>
+ </tr>
+ </j:if>
+
+ <d:invokeBody />
+ <j:forEach var="d" items="${descriptors}">
+ <f:optionalBlock name="${d.jsonSafeClassName}" help="${d.helpFile}"
+ title="${d.displayName}" checked="${instances.get(d)!=null}">
+
+ <j:set var="descriptor" value="${d}" />
+ <j:set var="instance" value="${instances.get(d)}" />
+ <st:include from="${d}" page="${d.configPage}" optional="true" />
+ </f:optionalBlock>
+ </j:forEach>
+ </f:section>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/descriptorRadioList.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/descriptorRadioList.jelly
new file mode 100644
index 0000000..66cd057
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/descriptorRadioList.jelly
@@ -0,0 +1,56 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Generate config pages from a list of Descriptors into a section.
+
+ <st:attribute name="title" use="required">
+ Human readable title of the section to be rendered in HTML.
+ </st:attribute>
+ <st:attribute name="descriptors" use="required">
+ hudson.model.Descriptor collection whose configuration page is rendered.
+ </st:attribute>
+ <st:attribute name="instance" use="required">
+ The currently configured instance used to fill the initial values of the form.
+ </st:attribute>
+ <st:attribute name="targetType">
+ the type for which descriptors will be configured.
+ default to ${it.class}
+ </st:attribute>
+ <st:attribute name="varName" use="required">
+ Used as a variable name as well as block name.
+ </st:attribute>
+ </st:documentation>
+
+ <j:set var="targetType" value="${attrs.targetType?:it.class}"/>
+ <f:section title="${attrs.title}">
+ <d:invokeBody />
+ <j:forEach var="d" items="${descriptors}" varStatus="loop">
+ <f:radioBlock name="${varName}" help="${d.helpFile}" value="${loop.index}"
+ title="${d.displayName}" checked="${instance.descriptor==d}">
+ <j:set var="descriptor" value="${d}" />
+ <j:set var="instance" value="${instance.descriptor==d?instance:null}" />
+ <f:invisibleEntry>
+ <input type="hidden" name="stapler-class" value="${descriptor.clazz.name}"/>
+ </f:invisibleEntry>
+ <st:include from="${d}" page="${d.configPage}" optional="true" />
+ </f:radioBlock>
+ </j:forEach>
+ </f:section>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/detail.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/detail.jelly
new file mode 100644
index 0000000..1b202d2
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/detail.jelly
@@ -0,0 +1,20 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2011 Sonatype, Inc.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core">
+ <div id='shutdown-msg'>Hudson is preparing to shutdown</div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/digest.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/digest.jelly
new file mode 100644
index 0000000..55b1c7b
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/digest.jelly
@@ -0,0 +1,21 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe, id:cactusman
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ ${%No changes.}
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/dir.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/dir.jelly
new file mode 100644
index 0000000..7671d65
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/dir.jelly
@@ -0,0 +1,97 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Erik Ramfelt, id:cactusman
+#
+#
+#************************************************************************** -->
+
+
+<!-- Show files in the workspace -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="${it.title} : ${path}">
+ <st:include page="sidepanel.jelly" it="${it.owner}"/>
+ <l:main-panel>
+ <div class="dirTree">
+ <!-- parent path -->
+ <div class="parentPath">
+ <form action="${backPath}" method="get">
+ <a href="${topPath}"><img src="${imagesURL}/48x48/${icon}" class="rootIcon" alt=""/></a>
+ <j:forEach var="p" items="${parentPath}">
+ <a href="${p.href}">${p.title}</a>
+ /
+ </j:forEach>
+ <input type="text" name="pattern" value="${pattern}" />
+ <img src="${imagesURL}/16x16/go-next.png" style="vertical-align:middle; cursor:pointer" alt="[submit]"
+ onclick="this.parentNode.submit()"/>
+ </form>
+ </div>
+ <j:choose>
+ <j:when test="${empty(files)}">
+ ${%No files in directory}
+ </j:when>
+ <j:otherwise>
+ <table class="fileList">
+ <j:forEach var="f" items="${files}">
+ <j:set var="x" value="${f.get(f.size()-1)}"/>
+ <tr>
+ <td>
+ <img src="${imagesURL}/16x16/${x.iconName}" alt=""/>
+ </td>
+ <td>
+ <j:forEach var="t" items="${f}" varStatus="st">
+
+ <j:choose>
+ <j:when test="${x.readable}">
+ <a href="${t.href}">${t.title}</a>
+ </j:when>
+ <j:otherwise>
+ ${t.title}
+ </j:otherwise>
+ </j:choose>
+
+ <j:if test="${!st.last}">/</j:if>
+ </j:forEach>
+ </td>
+ <j:if test="${!x.folder}">
+ <td class="fileSize">
+ ${x.getSize()}
+ </td>
+ <td>
+ <j:if test="${x.readable}">
+ <a href="${x.href}/*fingerprint*/">
+ <img src="${imagesURL}/16x16/fingerprint.png" alt="fingerprint" />
+ </a>
+ <st:nbsp/>
+ <a href="${x.href}/*view*/">${%view}</a>
+ </j:if>
+ </td>
+ </j:if>
+ </tr>
+ </j:forEach>
+ <tr>
+ <td style="text-align:right;" colspan="3">
+ <div style="margin-top: 1em;">
+ <a href="${backPath}${pattern!=''?pattern+'/':''}*zip*/${dir.name}.zip">
+ <img src="${imagesURL}/16x16/package.png"/>
+ (${%all files in zip})
+ </a>
+ </div>
+ </td>
+ </tr>
+ </table>
+ </j:otherwise>
+ </j:choose>
+ </div>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/disconnect.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/disconnect.jelly
new file mode 100644
index 0000000..3cb69b5
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/disconnect.jelly
@@ -0,0 +1,32 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe
+#
+#
+#************************************************************************** -->
+
+
+<!-- Disconnect confirmation -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="${it.displayName} ${%disconnect}">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <form method="post" action="doDisconnect">
+ ${%Are you sure about disconnecting?}
+ <f:submit value="${%Yes}" />
+ <p>${%blurb}</p>
+ <f:textarea name="offlineMessage" />
+ </form>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/downgrade.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/downgrade.jelly
new file mode 100644
index 0000000..1c72332
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/downgrade.jelly
@@ -0,0 +1,28 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <div class="downgrade">
+ <j:if test="${app.updateCenter.downgradable}">
+ <form method="post" action="${rootURL}/updateCenter/downgrade">
+ <br/>${%Restore the previous version of Hudson}
+ <f:submit value="${%buttonText(app.updateCenter.backupVersion)}"/>
+ </form>
+ </j:if>
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/dropdownDescriptorSelector.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/dropdownDescriptorSelector.jelly
new file mode 100644
index 0000000..d7b94bf
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/dropdownDescriptorSelector.jelly
@@ -0,0 +1,53 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2010, InfraDNA, Inc.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Renders a single &lt;select> control for choosing a Describable.
+ Depending on the currently selected value, its config.jelly will be
+ rendered below &lt;select, allowing the user to configure Describable.
+
+ <st:attribute name="field" use="required">
+ form field name. Used for databinding.
+ </st:attribute>
+ <st:attribute name="title" use="required">
+ Human readable title of this control.
+ </st:attribute>
+ <st:attribute name="descriptors">
+ Collection that lists up all the valid candidate descriptors.
+ If unspecified, inferred from the type of the field.
+ </st:attribute>
+ <st:attribute name="default">
+ If specified, this will be chosen as the default value in case the current selection is null.
+ </st:attribute>
+ </st:documentation>
+
+ <j:set target="${attrs}" property="descriptors" value="${attrs.descriptors ?: descriptor.getPropertyType(instance,attrs.field).getApplicableDescriptors()}" />
+
+ <f:dropdownList name="${attrs.field}" title="${attrs.title}" help="${descriptor.getHelpFile(attrs.field)}">
+ <d:invokeBody />
+
+ <j:set var="current" value="${instance[attrs.field]}"/>
+ <j:forEach var="descriptor" items="${attrs.descriptors}" varStatus="loop">
+ <f:dropdownListBlock value="${loop.index}" title="${descriptor.displayName}"
+ selected="${current.descriptor==descriptor || (current==null and descriptor==attrs.default)}" staplerClass="${descriptor.clazz.name}">
+ <j:set var="instance" value="${current.descriptor==descriptor ? current : null}" />
+ <st:include from="${descriptor}" page="${descriptor.configPage}" />
+ </f:dropdownListBlock>
+ </j:forEach>
+ </f:dropdownList>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/dropdownList.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/dropdownList.jelly
new file mode 100644
index 0000000..11b7f0f
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/dropdownList.jelly
@@ -0,0 +1,74 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Stephen Connolly
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout"
+ xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Foldable block expanded when the corresponding item is selected in the drop-down list.
+
+ <st:attribute name="title">
+ Human readable title text of this drop-down listbox.
+ Shown in the same position as &lt;f:entry title="..." />
+ </st:attribute>
+ <st:attribute name="name" use="required">
+ name of the drop-down list.
+ </st:attribute>
+ <st:attribute name="help">
+ Path to the inline help. See &lt;f:entry help="..." />
+ </st:attribute>
+ </st:documentation>
+
+ <tr>
+ <td class="setting-leftspace"><st:nbsp/></td>
+ <td class="setting-name">
+ ${attrs.title}
+ </td>
+ <td class="setting-main">
+ <!-- create drop-down list -->
+ <select class="setting-input dropdownList" onchange="updateDropDownList(this)">
+ <j:set var="dropdownListMode" value="createSelectField"/>
+ <d:invokeBody/>
+ </select>
+ </td>
+ <j:if test="${attrs.help!=null}">
+ <td class="setting-help">
+ <a href="#" class="help-button" helpURL="${rootURL}${attrs.help}"><img src="${imagesURL}/16x16/help.png"
+ alt="Help for feature: ${title}"/></a>
+ </td>
+ </j:if>
+ </tr>
+
+ <!-- generate the actual form entries -->
+ <tr class="dropdownList-container">
+ <td colspan="2"/>
+ <td colspan="2">
+ <table width="100%" name="${name}">
+ <j:set var="dropdownListMode" value="generateEntries"/>
+ <d:invokeBody/>
+ </table>
+ </td>
+ </tr>
+
+ <j:if test="${!empty(attrs.description)}">
+ <f:description>
+ <j:out value="${description}"/>
+ </f:description>
+ </j:if>
+ <j:if test="${attrs.help!=null}">
+ <f:helpArea/>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/dropdownListBlock.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/dropdownListBlock.jelly
new file mode 100644
index 0000000..026b621
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/dropdownListBlock.jelly
@@ -0,0 +1,51 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Foldable block expanded when the corresponding item is selected in the drop-down list.
+
+ <st:attribute name="value" use="required">
+ value of the list item. set to &lt;option value="...">
+ </st:attribute>
+ <st:attribute name="title" use="required">
+ human readable text displayed for this list item.
+ </st:attribute>
+ <st:attribute name="selected" type="boolean">
+ is this value initially selected?
+ </st:attribute>
+ <st:attribute name="staplerClass">
+ provide hint for stapler data binding.
+ typically set to ${descriptor.clazz.name} if dropdownList is for a list of descriptors.
+ </st:attribute>
+ </st:documentation>
+ <j:choose>
+ <j:when test="${dropdownListMode=='createSelectField'}">
+ <f:option selected="${attrs.selected}" value="${value}">${title}</f:option>
+ </j:when>
+ <j:when test="${dropdownListMode=='generateEntries'}">
+ <!-- sandwich them by markers so that we know what to show/hide -->
+ <tr class="dropdownList-start" style="display:none">
+ <j:if test="${!empty(attrs.staplerClass)}">
+ <td><input type="hidden" name="stapler-class" value="${attrs.staplerClass}"/></td>
+ </j:if>
+ </tr>
+ <d:invokeBody />
+ <tr class="dropdownList-end" style="display:none" />
+ </j:when>
+ </j:choose>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/editDescription.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/editDescription.jelly
new file mode 100644
index 0000000..5903637
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/editDescription.jelly
@@ -0,0 +1,32 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Eric Lefevre-Ardant
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ If JavaScript is off, this form is used to edit the description
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="${it.displayName}" norefresh="true">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <form action="submitDescription" method="post">
+ <f:textarea name="description" value="${it.description}" />
+ <f:submit value="${%Submit}" />
+ </form>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/editTypeIcon.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/editTypeIcon.jelly
new file mode 100644
index 0000000..00bc95c
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/editTypeIcon.jelly
@@ -0,0 +1,25 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Displays the edit type icon.
+ <%@ attribute name="type" type="hudson.scm.EditType" required="true" %>
+-->
+<?jelly escape-by-default='true'?>
+<img width="16" height="16"
+ src="${imagesURL}/16x16/document_${type.name}.png"
+ title="${type.description}" alt="${type.description}" />
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/editableComboBox.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/editableComboBox.jelly
new file mode 100644
index 0000000..64d69c2
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/editableComboBox.jelly
@@ -0,0 +1,54 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Bruce Chapman, Alan Harder
+#
+#
+#************************************************************************** -->
+
+
+<!-- Tomcat doesn't like us using the attribute called 'class' -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Editable drop-down combo box. Deprecated as of 1.356. Use f:combobox and databinding instead.
+
+ <st:attribute name="clazz">
+ Additional CSS classes that the control gets.
+ </st:attribute>
+ <st:attribute name="items">
+ List of possible values. Either this or nested &lt;f:editableComboBoxValue/>s are required.
+ </st:attribute>
+ <st:attribute name="field">
+ Used for databinding.
+ </st:attribute>
+ </st:documentation>
+
+ <st:once>
+ <script type="text/javascript" src="${request.contextPath}/scripts/utilities.js"/>
+ <script type="text/javascript" src="${request.contextPath}/scripts/combobox.js"/>
+ </st:once>
+
+ <f:prepareDatabinding/>
+
+ <input id="${attrs.id}" autocomplete="off" class="combobox ${attrs.clazz}${attrs.checkUrl!=null ? ' validated' : ''}"
+ name="${attrs.name ?: '_.'+attrs.field}"
+ value="${attrs.value ?: instance[attrs.field]}"
+ checkUrl="${attrs.checkUrl}" />
+ <div class="combobox-values">
+ <j:if test="${items!=null}">
+ <j:forEach var="v" items="${items}">
+ <f:editableComboBoxValue value="${v}" />
+ </j:forEach>
+ </j:if>
+ <d:invokeBody />
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/editableComboBoxValue.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/editableComboBoxValue.jelly
new file mode 100644
index 0000000..faec618
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/editableComboBoxValue.jelly
@@ -0,0 +1,26 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Alan Harder
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler">
+ <st:documentation>
+ Used inside &lt;f:editableComboBox/> to specify one value of a combobox.
+ Normally one would use multiple values.
+ <st:attribute name="value" use="required" />
+ </st:documentation>
+ <div value="${value}"/>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/editableDescription.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/editableDescription.jelly
new file mode 100644
index 0000000..8df1040
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/editableDescription.jelly
@@ -0,0 +1,49 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Tom Huybrechts, Yahoo! Inc.
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Renders ${it.description} and then allow it to be editable in place,
+ if the current user has the specified permission.
+
+ <st:attribute name="permission" use="required">
+ If the current user doesn't have this permission, the description
+ is not editable.
+ </st:attribute>
+ </st:documentation>
+
+ <div id="description">
+ <div>
+ <j:out value="${it.description!=null ? app.markupFormatter.translate(it.description) : ''}" />
+ </div>
+
+ <l:hasPermission permission="${permission}">
+ <div align="right"><a href="editDescription" onclick="${h.isAutoRefresh(request) ? null : 'return replaceDescription();'}">
+ <img src="${imagesURL}/16x16/notepad.png" alt="" />
+ <j:choose>
+ <j:when test="${empty(it.description)}">
+ ${%add description}
+ </j:when>
+ <j:otherwise>
+ ${%edit description}
+ </j:otherwise>
+ </j:choose>
+ </a></div>
+ </l:hasPermission>
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/entries.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/entries.jelly
new file mode 100644
index 0000000..6f3e938
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/entries.jelly
@@ -0,0 +1,28 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Render build histories.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <j:set target="${it}" property="nextBuildNumberToFetch" value="${it.owner.nextBuildNumber}"/>
+ <!-- build history -->
+ <j:forEach var="build" items="${it.renderList}">
+ <st:include page="entry.jelly" />
+ </j:forEach>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/entry.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/entry.jelly
new file mode 100644
index 0000000..7ca4fbb
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/entry.jelly
@@ -0,0 +1,90 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ An entry of the &lt;f:form>, which is one logical row (that consists of
+ several &lt;TR> tags.
+
+ One entry normally host one control.
+
+ <st:attribute name="title">
+ Name of the entry. Think of this like a label for the control.
+ </st:attribute>
+ <st:attribute name="field">
+ Used for the databinding. TBD. When this attribute
+ is specified, @help is inferred, and nested input controls don't need
+ the @field nor @name.
+ </st:attribute>
+ <st:attribute name="description">
+ If it's not obvious to the user as to what the control expects,
+ specify some description text (which currently gets rendered as
+ small text under the control, but that may change.)
+
+ This text shouldn't get too long, and in recent Hudson, this feature
+ is somewhat de-emphasized, in favor of the inline foldable help page
+ specified via @help.
+ </st:attribute>
+ <st:attribute name="isPropertyOverridden">
+ if present and true - value is overridden
+ </st:attribute>
+ <st:attribute name="help">
+ URL to the HTML page. When this attribute is specified, the entry gets
+ a (?) icon on the right, and if the user clicks it, the contents of the
+ given URL is rendered as a box below the entry.
+
+ The URL should return an HTML document wrapped in a &lt;div> tag.
+ The URL is interpreted to be rooted at the context path of Hudson,
+ so it's normally something like "/plugin/foobar/help/abc.html".
+ </st:attribute>
+ </st:documentation>
+ <j:if test="${attrs.help==null and attrs.field!=null}">
+ <!-- infer the help page from the current descriptor and field if possible -->
+ <j:set target="${attrs}" property="help"
+ value="${descriptor.getHelpFile(attrs.field)}" />
+ </j:if>
+ <j:if test="${attrs.isPropertyOverridden==null}">
+ <j:set target="${attrs}" property="isPropertyOverridden" value="false"/>
+ </j:if>
+ <!-- expose this so that we can look up the @field value later from prepareDatabinding.jelly -->
+ <j:set var="entry" value="${attrs}" />
+ <tr class="${attrs.isPropertyOverridden? 'modified': 'original'}">
+ <td class="setting-leftspace"><st:nbsp/></td>
+ <td class="setting-name">
+ <j:out value="${attrs.title}" />
+ </td>
+ <td class="setting-main">
+ <d:invokeBody />
+ </td>
+ <j:if test="${attrs.help!=null}">
+ <td class="setting-help">
+ <a href="#" class="help-button" helpURL="${rootURL}${attrs.help}"><img src="${imagesURL}/16x16/help.png" alt="Help for feature: ${title}" /></a>
+ </td>
+ </j:if>
+ </tr>
+ <!-- used to display the form validation error -->
+ <tr class="validation-error-area"><td colspan="2" /><td /></tr>
+ <j:if test="${!empty(attrs.description)}">
+ <f:description isPropertyOverridden="${attrs.isPropertyOverridden}">
+ <j:out value="${description}"/>
+ </f:description>
+ </j:if>
+ <j:if test="${attrs.help!=null}">
+ <f:helpArea />
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/enum.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/enum.jelly
new file mode 100644
index 0000000..27ff875
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/enum.jelly
@@ -0,0 +1,36 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Binds an enum field to a &lt;select> element.
+ The body of this tag is evaluated for each enum value,
+ which is passed as 'it'.
+
+ <st:attribute name="field">
+ Used for databinding. TBD.
+ </st:attribute>
+ </st:documentation>
+ <select class="setting-input" name="${field}">
+ <j:forEach var="it" items="${descriptor.getPropertyType(instance,field).enumConstants}">
+ <f:option value="${it.name()}" selected="${it==instance[field]}">
+ <d:invokeBody />
+ </f:option>
+ </j:forEach>
+ </select>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/enumSet.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/enumSet.jelly
new file mode 100644
index 0000000..874b38e
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/enumSet.jelly
@@ -0,0 +1,35 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Binds a set of Enum to a list of checkboxes, each with the label taken from enum Enum.toString()
+ Should be used inside an &lt;f:entry field='...'> element.
+ <st:attribute name="field" implicit="true">
+ Used for databinding.
+ </st:attribute>
+ </st:documentation>
+ <div name="${field}">
+ <j:forEach var="e" items="${descriptor.getPropertyType(instance,field).itemType.enumConstants}">
+ <div>
+ <input type="checkbox" name="_.${e.name()}" checked="${instance[field].contains(e)?'true':null}"/>
+ <label class="attach-previous">${e}</label>
+ </div>
+ </j:forEach>
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/error.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/error.jelly
new file mode 100644
index 0000000..dbc0881
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/error.jelly
@@ -0,0 +1,52 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2010, CloudBees, Inc.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#************************************************************************** -->
+
+<!--
+ * The MIT License
+ *
+ * Copyright (c) 2010, CloudBees, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ -->
+
+
+<!--
+ This is used to create the first user.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:statusCode value="403" />
+ <l:layout title="${%loginError(it.identifier.pronoun)}">
+ <l:main-panel>
+ <h1>${%loginError(it.identifier.pronoun)}</h1>
+ <p>${%blurb(it.identifier.pronoun, it.identifier.identifier)}</p>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/executors.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/executors.jelly
new file mode 100644
index 0000000..102b57b
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/executors.jelly
@@ -0,0 +1,163 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi,
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:local="local">
+ <st:documentation>
+ Displays the status of executors.
+ <st:attribute name="computers">
+ If specified, this is the list of computers whose executors are rendered. If omitted, all the computers
+ in the system will be rendered.
+ </st:attribute>
+ </st:documentation>
+ <d:taglib uri="local">
+ <d:tag name="computerCaption">
+ <a href="${rootURL}/${c.url}" title="${c.node!=null? c.node.nodeDescription : ''}">${title}</a><st:nbsp/>
+ <j:choose>
+ <j:when test="${c.offline}">
+ ${%offline}
+ </j:when>
+ <j:when test="${!c.acceptingTasks}">
+ ${%suspended}
+ </j:when>
+ <j:when test="${c.oneOffExecutorsCount != 0}">
+ ${c.busyCount}/${c.executorsCount}+${c.oneOffExecutorsCount}
+ </j:when>
+ <j:otherwise>
+ ${c.busyCount}/${c.executorsCount}
+ </j:otherwise>
+ </j:choose>
+ </d:tag>
+ <d:tag name="executor">
+ <j:if test="${!e.idle}">
+ <tr>
+ <j:choose>
+ <j:when test="${!e.alive}">
+ <td class="pane">
+ <a href="${rootURL}/${c.url}${url}/causeOfDeath">
+ <div class="error">${%Dead} (!)</div>
+ </a>
+ </td>
+ <td class="pane"/>
+ </j:when>
+ <j:otherwise>
+ <!-- not actually optional, but it helps with backward compatibility -->
+ <j:set var="executor" value="${e}"/>
+ <st:include it="${e.currentExecutable}" page="executorCell.jelly" optional="true">
+ <td class="pane">
+ <div style="white-space: normal">${%Building}
+ <j:set var="exe" value="${e.currentExecutable}" />
+ <j:invokeStatic var="exeparent"
+ className="hudson.model.queue.Executables" method="getParentOf">
+ <j:arg type="hudson.model.Queue$Executable" value="${exe}" />
+ </j:invokeStatic>
+ <j:choose>
+ <j:when test="${h.hasPermission(exeparent,exeparent.READ)}">
+ <a href="${rootURL}/${exeparent.url}">${exeparent.fullDisplayName}</a>&#160;<a href="${rootURL}/${exe.url}">#${exe.number}</a>
+ <t:buildProgressBar build="${exe}" executor="${executor}"/>
+ </j:when>
+ <j:otherwise>
+ <span>${%Unknown Task}</span>
+ </j:otherwise>
+ </j:choose>
+ </div>
+ </td>
+ </st:include>
+ <td class="pane" width="16" align="center" valign="middle">
+ <j:if test="${e.hasStopPermission()}">
+ <a href="${rootURL}/${c.url}${url}/stop">
+ <img src="${imagesURL}/16x16/stop.png" alt="${%terminate this build}"/>
+ </a>
+ </j:if>
+ </td>
+ </j:otherwise>
+ </j:choose>
+ </tr>
+ </j:if>
+ </d:tag>
+ </d:taglib>
+ <j:set var="computers" value="${attrs.computers?:app.computers}"/>
+ <l:pane width="2" id="executors" title="&lt;a href='${rootURL}/computer/'>${%Build Executor Status}&lt;/a>">
+ <colgroup>
+ <col width="200*"/>
+ <col width="24"/>
+ </colgroup>
+ <j:forEach var="c" items="${computers}">
+ <tr>
+ <j:choose>
+ <j:when test="${c.node==app or computers.size()==1}">
+ <th class="pane" colspan="2">
+ <j:choose>
+ <j:when test="${empty(app.slaves) or computers.size()==1}">
+ <local:computerCaption title="Status"/>
+ </j:when>
+ <j:otherwise>
+ <local:computerCaption title="Master"/>
+ </j:otherwise>
+ </j:choose>
+ </th>
+ </j:when>
+ <j:otherwise>
+ <th class="pane" colspan="2">
+ <local:computerCaption title="${c.displayName}"/>
+ </th>
+ </j:otherwise>
+ </j:choose>
+ </tr>
+
+ <j:choose>
+ <j:when test="${c.connecting}">
+ <tr>
+ <td class="pane" colspan="2">
+ Connecting
+ </td>
+ </tr>
+ </j:when>
+
+ <j:when test="${c.offline}">
+ <tr>
+ <td class="pane" colspan="2">
+ Offline
+ </td>
+ </tr>
+ </j:when>
+
+ <j:when test="${c.idle}">
+ <tr>
+ <td class="pane" colspan="2">
+ Idle
+ </td>
+ </tr>
+ </j:when>
+
+ <j:otherwise>
+ <j:forEach var="e" items="${c.executors}" varStatus="eloop">
+ <local:executor name="${eloop.index+1}" url="executors/${eloop.index}"/>
+ </j:forEach>
+ <j:forEach var="e" items="${c.oneOffExecutors}" varStatus="eloop">
+ <local:executor name="" url="oneOffExecutors/${eloop.index}"/>
+ </j:forEach>
+ </j:otherwise>
+ </j:choose>
+ </j:forEach>
+ </l:pane>
+ <!-- schedule updates only for the full page reload -->
+ <j:if test="${ajax==null and !h.isAutoRefresh(request) and h.hasPermission(app.READ)}">
+ <script defer="defer">
+ refreshPart('executors',"${h.hasView(it,'ajaxExecutors')?'.':rootURL}/ajaxExecutors");
+ </script>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/expandButton.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/expandButton.jelly
new file mode 100644
index 0000000..e990b9a
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/expandButton.jelly
@@ -0,0 +1,35 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Start off as a button, but upon clicking, it replaces itself
+ with the body of the tag. This works like <f:advancedButton />
+ but it is designed to be used outside a config form.
+
+ Attributes:
+ @title : title of the button. required.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <div class="advancedLink">
+ <input type="button" value="${attrs.title}" class="expandButton" />
+ </div>
+ <div style="display:none">
+ <!-- this is the hidden portion to be expanded -->
+ <d:invokeBody/>
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/expandableTextbox.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/expandableTextbox.jelly
new file mode 100644
index 0000000..b3f3be8
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/expandableTextbox.jelly
@@ -0,0 +1,75 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ TODO: support @checkUrl
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:d="jelly:define" xmlns:f="/lib/form" xmlns:st="jelly:stapler">
+ <st:documentation>
+ single-line textbox that can be expanded into a multi-line textarea.
+
+ This control is useful for a field that expects multiple whitespaec-separated tokens
+ (such as URLs, glob patterns, etc.) When the user only enters a few tokens,
+ they can keep it as a single line to save space, but to enter a large number of values,
+ this can be turned into textarea for better visibility.
+
+ If the initial value is already multi-line text, the control starts with
+ textarea.
+
+ On the server side, your program is responsible for treating ' ', \t, \r, and \n for
+ separators. (StringTokenizer would do this.)
+
+ <st:attribute name="field">
+ Used for databinding. TBD.
+ </st:attribute>
+ <st:attribute name="name">
+ This becomes @name of the &lt;input> tag.
+ If @field is specified, this value is inferred from it.
+ </st:attribute>
+ <st:attribute name="value">
+ The initial value of the field. This becomes the @value of the &lt;input> tag.
+ If @field is specified, the current property from the "instance" object
+ will be set as the initial value automatically,
+ which is the recommended approach.
+ </st:attribute>
+ </st:documentation>
+ <f:prepareDatabinding />
+ <j:set var="value" value="${attrs.value?:instance[attrs.field]}" />
+ <j:choose>
+ <j:when test="${h.isMultiline(value)}">
+ <!-- multiline text area to begin with -->
+ <f:textarea name='${attrs.name}' value="${value}" field="${attrs.field}"/>
+ </j:when>
+ <j:otherwise>
+ <!-- single line textbox with expand button -->
+ <table border="0" style="width:100%" cellspacing="0" cellpadding="0">
+ <tr>
+ <td width="*">
+ <j:set var="name" value="${attrs.name ?: '_.'+attrs.field}" />
+ <input class="setting-input" type="text"
+ name="${name}" value="${value}"
+ id="textarea.${name}" />
+ </td><td width="1">
+ <input type="button" value="&#x25BC;" onclick="expandTextArea(this,'textarea.${name}')"
+ tooltip="${%tooltip}"/>
+ </td>
+ </tr>
+ </table>
+ </j:otherwise>
+ </j:choose>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/feeds.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/feeds.jelly
new file mode 100644
index 0000000..f1a6259
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/feeds.jelly
@@ -0,0 +1,30 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!-- list of feed links -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <div align="right" style="margin:1em">
+ <img src="${imagesURL}/atom.gif" border="0" alt="Feed"/>
+ <st:nbsp/><st:nbsp/><st:nbsp/><st:nbsp/>
+ <a href="rss">${%All}</a>
+ <st:nbsp/><st:nbsp/><st:nbsp/><st:nbsp/>
+ <a href="rss?level=SEVERE">${%&gt; SEVERE}</a>
+ <st:nbsp/><st:nbsp/><st:nbsp/><st:nbsp/>
+ <a href="rss?level=WARNING">${%&gt; WARNING}</a>
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/fingerprintCheck.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/fingerprintCheck.jelly
new file mode 100644
index 0000000..a640695
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/fingerprintCheck.jelly
@@ -0,0 +1,45 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ New View page
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <l:layout norefresh="true">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <h1>
+ <img src="${imagesURL}/48x48/fingerprint.png" alt=""/>
+ ${%Check File Fingerprint}
+ </h1>
+ <f:form method="post" action="doFingerprintCheck" enctype="multipart/form-data">
+ <f:block>
+ <div style="margin-bottom: 1em;">
+ ${%description} (<a href="${%fingerprint.link}">${%more details}</a>)
+ </div>
+ </f:block>
+ <f:entry title="${%File to check}">
+ <input type="file" name="name" class="setting-input" />
+ </f:entry>
+ <f:block>
+ <f:submit value="${%Check}" />
+ </f:block>
+ </f:form>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/firstUser.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/firstUser.jelly
new file mode 100644
index 0000000..eea2e41
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/firstUser.jelly
@@ -0,0 +1,24 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ This is used to create the first user.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <local:_entryForm host="${it}" title="${%Create First Admin User}" action="createFirstAccount" captcha="${false}" xmlns:local="/hudson/security/HudsonPrivateSecurityRealm" />
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/floatingBox.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/floatingBox.jelly
new file mode 100644
index 0000000..92277fa
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/floatingBox.jelly
@@ -0,0 +1,47 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, id:cactusman
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:local="local">
+ <j:set var="tr" value="${action.lastTestResultAction}" />
+ <j:if test="${tr.previousResult!=null}">
+ <!-- at least two data points are required for a trend report -->
+ <div align="right">
+ <j:set var="mode" value="${h.getCookie(request,'TestResultAction_failureOnly').value}" />
+ <j:if test="${mode!=null}">
+ <j:set var="trendQueryString1" value="?failureOnly=${mode}" />
+ <j:set var="trendQueryString2" value="&amp;failureOnly=${mode}" />
+ </j:if>
+ <div class="test-trend-caption">
+ ${%Test Result Trend}
+ </div>
+ <div>
+ <img src="test/trend${trendQueryString1}" lazymap="test/trendMap${trendQueryString1}" alt="[Test result trend chart]"/>
+ </div>
+ <div style="text-align:right">
+ <a href="test/flipTrend">
+ <j:choose>
+ <!-- needs to strip whitespace here -->
+ <j:when test="${mode}">(${%show test # and failure #})</j:when>
+ <j:otherwise>(${%just show failures})</j:otherwise>
+ </j:choose>
+ </a> <st:nbsp/>
+ <a href="test/?width=800&amp;height=600${trendQueryString2}">${%enlarge}</a>
+ </div>
+ </div>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/foo.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/foo.jelly
new file mode 100644
index 0000000..7d3901b
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/foo.jelly
@@ -0,0 +1,19 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<b>JELLY TAG FILE ${value}</b>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/footer.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/footer.jelly
new file mode 100644
index 0000000..9f44fa2
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/footer.jelly
@@ -0,0 +1,34 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Periodically ask the client to deliver the usage statistics to the server for us.
+ This allows us to avoid proxy related configuration on the server,
+ and instead piggy-back on user connection.
+
+ This file is pulled into the layout.jelly
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:if test="${it.due}">
+ <script>
+ Behaviour.addLoadEvent(function() {
+ loadScript("http://hudson-ci.org/usage-stats.js?${it.statData}");
+ });
+ </script>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/form.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/form.jelly
new file mode 100644
index 0000000..458e5a8
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/form.jelly
@@ -0,0 +1,90 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Yahoo! Inc., CloudBees, Inc.
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Overall form that should be placed inside <l:main-panel>
+
+ Attributes:
+ @descriptors : collection of Descriptors
+ @nameTitle : title of the name text field
+ @copyTitle : title of the copy option
+ @copyNames : options of names to choose from as the copy source. null to hide "copy" option
+ @checkUrl : form field validation url
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form">
+ <j:set var="descriptors" value="${h.filterDescriptors(it,attrs.descriptors)}" />
+
+ <s:form method="post" action="createItem">
+ <s:entry title="${attrs.nameTitle}">
+ <s:textbox id="name" name="name" checkUrl="'${rootURL}/${attrs.checkUrl}?value='+encodeURIComponent(this.value)"
+ onchange="updateOk(this.form)" onkeyup="updateOk(this.form)" />
+ <script>$('name').focus();</script>
+ </s:entry>
+
+ <j:forEach var="descriptor" items="${descriptors}">
+ <s:block>
+ <input type="radio" name="mode" value="${descriptor.class.name}" onchange="updateOk(this.form)" onclick="updateOk(this.form)" />
+ <st:nbsp/>
+ <label class="attach-previous"><b>${descriptor.displayName}</b></label>
+ </s:block>
+ <s:entry>
+ <st:set var="instance" value="${descriptor}" />
+ <st:include page="newInstanceDetail.jelly" it="${descriptor}" />
+ </s:entry>
+ </j:forEach>
+ <j:if test="${!empty(attrs.copyNames)}">
+ <s:block>
+ <input type="radio" name="mode" value="copy" onchange="updateOk(this.form)" onclick="updateOk(this.form)" />
+ <st:nbsp/>
+ <label class="attach-previous"><b>${attrs.copyTitle}</b></label>
+ </s:block>
+ <s:entry>
+ ${%Copy from}
+ <s:editableComboBox id="from" name="from" items="${attrs.copyNames}" />
+ </s:entry>
+ </j:if>
+
+ <s:block>
+ <!--
+ when there's only one radio above, form.elements['mode]' won't return an array, which makes the script complex.
+ So always force non-empty array
+ -->
+ <input type="radio" name="mode" value="dummy1" style="display:none" />
+ <input type="radio" name="mode" value="dummy2" style="display:none" />
+ <input type="submit" name="Submit" value="OK" id="ok" style="margin-left:5em" />
+ </s:block>
+ </s:form>
+ <script><![CDATA[
+ var okButton = makeButton($('ok'),null);
+
+ function updateOk(form) {
+ function state() {
+ if($('name').value.length==0) return true;
+ var radio = form.elements['mode'];
+ if (radio.length==2) return false; // this means we only have dummy checkboxes
+ for(i=0;i<radio.length;i++)
+ if(radio[i].checked)
+ return false;
+ return true;
+ }
+
+ okButton.set('disabled',state(),false);
+ }
+ updateOk(okButton.getForm());
+ ]]></script>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/global.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/global.jelly
new file mode 100644
index 0000000..7fd43e9
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/global.jelly
@@ -0,0 +1,31 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:if test="${app.items.size()>10}">
+ <!--
+ unless you have a fair number of projects, this option is likely pointless.
+ so let's hide this option for new users to avoid confusing them.
+ -->
+ <f:section title="${%SCM Polling}">
+ <f:entry title="${%Max # of concurrent polling}" field="pollingThreadCount">
+ <f:textbox value="${descriptor.pollingThreadCount==0 ? '' : descriptor.pollingThreadCount}"/>
+ </f:entry>
+ </f:section>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/hasPermission.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/hasPermission.jelly
new file mode 100644
index 0000000..7f47b26
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/hasPermission.jelly
@@ -0,0 +1,30 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Tom Huybrechts
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:d="jelly:define" xmlns:st="jelly:stapler">
+ <st:documentation>
+ Renders the body only if the current user has the specified permission
+ <st:attribute name="permission" use="required" type="Permission">
+ permission object to check. If this is null, the body will be also rendered.
+ </st:attribute>
+ </st:documentation>
+
+ <j:if test="${h.hasPermission(it, permission)}">
+ <d:invokeBody/>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/header.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/header.jelly
new file mode 100644
index 0000000..accf0b9
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/header.jelly
@@ -0,0 +1,30 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:s="jelly:stapler" xmlns:d="jelly:define">
+ <s:documentation>
+ Header portion of the HTML page, that gets rendered into the &lt;head> tag.
+ Multiple &lt;l:header> elements can be specified, and can even come after
+ &lt;l:main-panel>.
+
+ This tag can be placed inside &lt;l:layout>.
+ </s:documentation>
+ <j:if test="${mode=='header'}">
+ <d:invokeBody />
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/help-launcher.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/help-launcher.jelly
new file mode 100644
index 0000000..a1200eb
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/help-launcher.jelly
@@ -0,0 +1,34 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:ajax>
+ <div>
+ ${%Controls how Hudson starts this slave.}
+
+ <dl>
+ <j:forEach var="d" items="${h.getComputerLauncherDescriptors()}">
+ <dt><b>${d.displayName}</b></dt>
+ <dd>
+ <st:include class="${d.clazz}" page="help.jelly" optional="true"/>
+ </dd>
+ </j:forEach>
+ </dl>
+ </div>
+ </l:ajax>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/help.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/help.jelly
new file mode 100644
index 0000000..ec4bf92
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/help.jelly
@@ -0,0 +1,24 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ (?) icon linked to the specified @href
+-->
+<?jelly escape-by-default='true'?>
+<a href="${href}">
+ <img src="${imagesURL}/16x16/help.png" alt="[help]"/>
+</a>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/helpArea.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/helpArea.jelly
new file mode 100644
index 0000000..eb2d094
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/helpArea.jelly
@@ -0,0 +1,30 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Place holder to lazy-load help text via AJAX.
+ </st:documentation>
+ <tr class="help-area">
+ <td/>
+ <td colspan="2">
+ <div class="help">${%Loading...}</div>
+ </td>
+ <td/>
+ </tr>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/hetero-list.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/hetero-list.jelly
new file mode 100644
index 0000000..039f95d
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/hetero-list.jelly
@@ -0,0 +1,127 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Nikita Levyankov
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:local="local">
+ <st:documentation>
+ Outer most tag for creating a heterogeneous list, where the user can choose arbitrary number of
+ arbitrary items from the given list of descriptors, and configure them independently.
+
+ The submission can be data-bound into List&lt;T> where T is the common base type for the describable instances.
+
+ <st:attribute name="name" use="required">
+ form name that receives an array for all the items in the heterogeneous list.
+ </st:attribute>
+ <st:attribute name="items" use="required" type="java.util.Collection">
+ existing items to be displayed. Something iterable, such as array or collection.
+ </st:attribute>
+ <st:attribute name="descriptors" use="required">
+ all types that the user can add.
+ </st:attribute>
+ <st:attribute name="addCaption">
+ caption of the 'add' button.
+ </st:attribute>
+ <st:attribute name="deleteCaption">
+ caption of the 'delete' button.
+ </st:attribute>
+ <st:attribute name="targetType">
+ the type for which descriptors will be configured. Defaults to ${it.class} (optional)
+ </st:attribute>
+ <st:attribute name="hasHeader">
+ For each item, add a caption from descriptor.getDisplayName().
+ This also activates drag&amp;drop (where the header is a grip), and help text support.
+ </st:attribute>
+ <st:attribute name="isPropertyOverridden">
+ if present and true - value is overridden
+ </st:attribute>
+ <st:attribute name="resetUrl">
+ If present, Redo icon will rendered and Reset will be available.
+ </st:attribute>
+ </st:documentation>
+ <d:taglib uri="local">
+ <d:tag name="body">
+ <table style="width:100%">
+ <j:set var="help" value="${descriptor.helpFile}" />
+ <j:if test="${hasHeader}">
+ <tr>
+ <td colspan="3">
+ <div class="dd-handle">
+ <b>${descriptor.displayName}</b>
+ </div>
+ </td>
+ <j:if test="${help!=null}">
+ <td>
+ <a href="#" class="help-button" helpURL="${rootURL}${help}"><img src="${imagesURL}/16x16/help.png" alt="[help]"/></a>
+ </td>
+ </j:if>
+ </tr>
+ <!-- TODO: help support is unintuitive; people should be able to see help from drop-down menu -->
+ <j:if test="${help!=null}">
+ <f:helpArea />
+ </j:if>
+ </j:if>
+ <!-- optional added to keep from breaking page rendering when
+ a descriptor doesn't have a config.jelly. -->
+ <st:include from="${descriptor}"
+ page="${descriptor.configPage}" optional="true" />
+ <f:block>
+ <div align="right">
+ <input type="hidden" name="stapler-class" value="${descriptor.clazz.name}" />
+ <f:repeatableDeleteButton value="${attrs.deleteCaption}" />
+ </div>
+ </f:block>
+ </table>
+ <input type="hidden" name="kind" value="${descriptor.class.name}" />
+ </d:tag>
+ </d:taglib>
+ <j:if test="${attrs.isPropertyOverridden==null}">
+ <j:set target="${attrs}" property="isPropertyOverridden" value="false"/>
+ </j:if>
+ <j:set var="targetType" value="${attrs.targetType?:it.class}"/>
+ <j:if test="${attrs.isPropertyOverridden and !empty(attrs.resetUrl)}">
+ <div class="hetero-list-reset">
+ <a href="#" class="reset-button" resetURL="${resetUrl}">
+ <img src="${imagesURL}/16x16/undo.png" alt="Reset ${title}"/>
+ </a>
+ </div>
+ </j:if>
+ <div class="hetero-list-container${hasHeader?' with-drag-drop':''}${attrs.isPropertyOverridden? ' modified' :''}">
+ <!-- display existing items -->
+ <j:forEach var="i" items="${attrs.items}">
+ <j:set var="descriptor" value="${i.descriptor}" />
+ <j:set var="instance" value="${i}" />
+ <div name="${attrs.name}" class="repeated-chunk">
+ <local:body deleteCaption="${attrs.deleteCaption}" />
+ </div>
+ </j:forEach>
+
+ <div class="repeatable-insertion-point" />
+ <div class="prototypes to-be-removed">
+ <!-- render one prototype for each type -->
+ <j:set var="instance" value="${null}" />
+ <j:forEach var="descriptor" items="${attrs.descriptors}" varStatus="loop">
+ <div name="${attrs.name}" title="${descriptor.displayName}" tooltip="${descriptor.tooltip}">
+ <local:body deleteCaption="${attrs.deleteCaption}" />
+ </div>
+ </j:forEach>
+ </div>
+
+ <div>
+ <input type="button" value="${attrs.addCaption?:'%Add'}" class="hetero-list-add" />
+ </div>
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/hetero-radio.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/hetero-radio.jelly
new file mode 100644
index 0000000..a8f9f5f
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/hetero-radio.jelly
@@ -0,0 +1,49 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:local="local">
+ <st:documentation>
+ Sibling of hetero-list, which only allows the user to pick one type from the list of descriptors and configure it.
+
+ <st:attribute name="field" use="required">
+ Field name in the parent object where databinding happens.
+ </st:attribute>
+ <st:attribute name="descriptors" use="required">
+ all types that the user can add.
+ </st:attribute>
+ </st:documentation>
+
+ <f:prepareDatabinding />
+
+ <table style="width:100%">
+ <j:set var="currentInstance" value="${instance[field]}" />
+ <j:set var="currentDescriptor" value="${currentInstance.descriptor}" />
+ <j:forEach var="d" items="${descriptors}" varStatus="loop">
+ <f:radioBlock name="${field}" help="${d.helpFile}" value="${loop.index}"
+ title="${d.displayName}" checked="${currentDescriptor==d}">
+ <j:set var="descriptor" value="${d}" />
+ <j:set var="instance" value="${currentDescriptor==d?currentInstance:null}" />
+ <st:include from="${d}" page="${d.configPage}" optional="true" />
+
+ <f:invisibleEntry><!-- this tells Stapler which block is for which class -->
+ <input type="hidden" name="stapler-class" value="${d.clazz.name}" />
+ </f:invisibleEntry>
+ </f:radioBlock>
+ </j:forEach>
+ </table>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/iconSize.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/iconSize.jelly
new file mode 100644
index 0000000..f865176
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/iconSize.jelly
@@ -0,0 +1,45 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <table style="width:100%">
+ <tr>
+ <d:taglib uri="local">
+ <d:tag name="iconSizeLink">
+ <st:nbsp/>
+ <j:choose>
+ <j:when test="${sz==iconSize}">
+ ${title}
+ </j:when>
+ <j:otherwise>
+ <a href="${rootURL}/iconSize?${sz}">${title}</a>
+ </j:otherwise>
+ </j:choose>
+ </d:tag>
+ </d:taglib>
+
+ <td xmlns:local="local">${%Icon}:
+ <local:iconSizeLink title="S" sz="16x16" />
+ <local:iconSizeLink title="M" sz="24x24" />
+ <local:iconSizeLink title="L" sz="32x32" />
+ </td><td>
+ <d:invokeBody />
+ </td>
+ </tr>
+ </table>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/inProgress.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/inProgress.jelly
new file mode 100644
index 0000000..a99baaa
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/inProgress.jelly
@@ -0,0 +1,31 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <l:layout norefresh="true">
+ <st:include it="${it.build}" page="sidepanel.jelly" />
+ <l:main-panel>
+ <h1>Build ${it.build.displayName}</h1>
+ <p>
+ ${%Tagging is in progress:}
+ </p>
+
+ <st:include page="log.jelly" />
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/index.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/index.jelly
new file mode 100644
index 0000000..45db4ef
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/index.jelly
@@ -0,0 +1,73 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2012 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Winston Prakash
+#
+#************************************************************************** -->
+
+<!--
+ Security Config page
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <l:layout norefresh="true" permission="${it.ADMINISTER}">
+ <st:include it="${app.primaryView}" page="sidepanel.jelly" xmlns:st="jelly:stapler" />
+ <l:main-panel>
+ <div class="behavior-loading">${%LOADING}</div>
+ <div><h1>Configure Security</h1></div>
+ <f:form method="post" name="config" action="configSubmit">
+
+ <f:optionalBlock name="use_security" title="${%Enable security}"
+ checked="${it.useSecurity}" help="/help/system-config/enableSecurity.html">
+ <f:entry title="${%TCP port for JNLP slave agents}"
+ help="/help/system-config/master-slave/slave-agent-port.html">
+ <f:radio name="slaveAgentPortType" value="fixed" id="sat.fixed"
+ checked="${it.slaveAgentPort gt 0}" onclick="$('sat.port').disabled=false"/>
+ <label for="sat.fixed">${%Fixed}</label> :
+ <input type="text" class="number" name="slaveAgentPort" id="sat.port"
+ value="${it.slaveAgentPort gt 0 ? it.slaveAgentPort : null}"
+ disabled="${it.slaveAgentPort gt 0 ? null : 'true'}"/>
+
+ <st:nbsp />
+
+ <f:radio name="slaveAgentPortType" value="random" id="sat.random"
+ checked="${it.slaveAgentPort==0}" onclick="$('sat.port').disabled=true" />
+ <label for="sat.random">${%Random}</label>
+
+ <st:nbsp />
+
+ <f:radio name="slaveAgentPortType" value="disable" id="sat.disabled"
+ checked="${it.slaveAgentPort==-1}" onclick="$('sat.port').disabled=true" />
+ <label for="sat.disabled">${%Disable}</label>
+ </f:entry>
+
+ <f:dropdownDescriptorSelector title="${%Markup Formatter}" field="markupFormatter" />
+
+ <f:entry title="${%Access Control}">
+ <table style="width:100%">
+ <f:descriptorRadioList title="${%Security Realm}" varName="realm"
+ instance="${it.securityRealm}"
+ descriptors="${h.securityRealmDescriptors}"/>
+ <f:descriptorRadioList title="${%Authorization}" varName="authorization"
+ instance="${it.authorizationStrategy}"
+ descriptors="${h.authorizationStrategyDescriptors}"/>
+ </table>
+ </f:entry>
+ </f:optionalBlock>
+
+ <f:block>
+ <f:submit value="${%Save}" />
+ </f:block>
+
+ </f:form>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/installed.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/installed.jelly
new file mode 100644
index 0000000..5e6f513
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/installed.jelly
@@ -0,0 +1,157 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe, Yahoo! Inc.
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Config page
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form">
+ <l:layout title="Update Center" permission="${app.ADMINISTER}" norefresh="true">
+ <st:include page="sidepanel.jelly"/>
+ <l:main-panel>
+ <local:tabBar page="installed" xmlns:local="/hudson/PluginManager" />
+ <table id="plugins" class="sortable pane bigtable">
+ <j:choose>
+ <j:when test="${empty(app.pluginManager.plugins) and empty(app.pluginManager.failedPlugins)}">
+ <tr><td>
+ ${%No plugins installed.}
+ </td></tr>
+ </j:when>
+ <j:otherwise>
+ <tr style="border-top: 0px;">
+ <th width="32" tooltip="${%Uncheck to disable the plugin}">${%Enabled}</th>
+ <th initialSortDir="down">${%Name}</th>
+ <th width="32">${%Version}</th>
+ <th width="32">${%Previously installed version}</th>
+ <th width="32">${%Pinned}</th>
+ </tr>
+ <j:forEach var="p" items="${app.pluginManager.plugins}">
+ <tr>
+ <j:set var="state" value="${p.enabled?'true':null}"/>
+ <td class="center pane" data="${state}">
+ <input type="checkbox" checked="${state}" onclick="flip(event)"
+ url="plugin/${p.shortName}"
+ original="${p.active?'true':'false'}"/>
+ </td>
+ <td class="pane">
+ <div>
+ <a href="${p.url}">
+ ${p.updateInfo.title?:p.longName}
+ </a>
+ </div>
+ <div class="excerpt">
+ <j:set var="indexPage" value="${p.indexPage.toString()}" />
+ <j:if test="${!empty(indexPage)}">
+ <j:include uri="${indexPage}" />
+ </j:if>
+ </div>
+ </td>
+ <td class="center pane" style="white-space:nowrap">
+ ${p.version}
+ </td>
+ <td>
+ <j:if test="${p.downgradable}">
+ <form method="post" action="${rootURL}/updateCenter/plugin/${p.shortName}/downgrade">
+ <s:submit value="${%downgradeTo(p.backupVersion)}"/>
+ </form>
+ </j:if>
+ </td>
+ <td class="center pane" id='unpin-${p.shortName}'>
+ <j:if test="${p.isPinned()}">
+ <input type="button" onclick="unpin(this,'${p.shortName}')" value="${%Unpin}" class="yui-button" />
+ <a href="${%wiki.url}"><img style="vertical-align:top" src="${imagesURL}/16x16/help.png"/></a>
+ </j:if>
+ </td>
+ </tr>
+ </j:forEach>
+ <!-- failed ones -->
+ <j:forEach var="p" items="${it.pluginManager.failedPlugins}">
+ <tr class="hoverback">
+ <td class="pane" />
+ <td class="pane">
+ <h4 class="error">Failed : ${p.name}</h4>
+ <div stlyle="padding-left: 1em">
+ <pre>${p.exceptionString}</pre>
+ </div>
+ </td>
+ <td class="pane" />
+ </tr>
+ </j:forEach>
+ </j:otherwise>
+ </j:choose>
+ </table>
+
+ <j:if test="${it.isPluginUploaded()}">
+ <div style="margin: 1em; height: 1em">
+ <div class="error">
+ ${%New plugins will take effect once you restart Hudson}
+ <j:if test="${app.lifecycle.canRestart()}">
+ <s:submit value="${%Restart Once No Jobs Are Running}" />
+ </j:if>
+ </div>
+ </div>
+ </j:if>
+ <div class="warning" id="needRestart" style="display:none; margin: 1em; height: 1em">
+ <form method="post" action="${rootURL}/safeRestart">
+ ${%Changes will take effect when you restart Hudson}
+ <j:if test="${app.lifecycle.canRestart()}">
+ <s:submit value="${%Restart Once No Jobs Are Running}" />
+ </j:if>
+ </form>
+ </div>
+
+
+ <script>
+ <!-- function to toggle the enable/disable state -->
+ function flip(o) {
+ btn = Event.element(o);
+
+ <!-- trigger -->
+ new Ajax.Request(btn.getAttribute('url')+"/make"+(btn.checked?"Enable":"Disable")+"d", {
+ onFailure : function(req,o) {
+ $('needRestart').innerHTML = req.responseText;
+ }
+ });
+
+ updateMsg();
+ }
+
+ function updateMsg() {
+ <!-- is anything changed since its original state? -->
+ var e = $A($('plugins').getElementsByTagName('input')).find(function(e) {
+ return String(e.checked)!=e.getAttribute('original');
+ });
+
+ $('needRestart').style.display = (e!=null?"block":"none");
+ }
+
+ updateMsg(); // set the initial state
+
+ function unpin(button,shortName) {
+ new Ajax.Request("./plugin/"+shortName+"/unpin", {
+ onFailure : function(t) {
+ alert('Failed to unpin:'+t.responseText);
+ },
+ onSuccess : function(t) {
+ $('unpin-'+shortName).innerHTML = "";
+ }
+ });
+ }
+ </script>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/invisibleEntry.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/invisibleEntry.jelly
new file mode 100644
index 0000000..1049bcb
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/invisibleEntry.jelly
@@ -0,0 +1,28 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2010, InfraDNA, Inc.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Invisible &lt;f:entry> type. Useful for adding hidden field values.
+ </st:documentation>
+ <tr style="display:none">
+ <td>
+ <d:invokeBody />
+ </td>
+ </tr>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/isAdmin.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/isAdmin.jelly
new file mode 100644
index 0000000..29f2d0d
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/isAdmin.jelly
@@ -0,0 +1,23 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:d="jelly:define" xmlns:s="jelly:stapler">
+ <j:if test="${h.hasPermission(app.ADMINISTER)}">
+ <d:invokeBody />
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/isAdminOrTest.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/isAdminOrTest.jelly
new file mode 100644
index 0000000..215cfd8
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/isAdminOrTest.jelly
@@ -0,0 +1,34 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Stephen Connolly
+#
+#
+#************************************************************************** -->
+
+
+<!--
+<%@ attribute name="test" required="true" type="java.lang.Boolean" %>
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:d="jelly:define" xmlns:s="jelly:stapler">
+ <j:choose>
+ <j:when test="${!test &amp;&amp; app.useSecurity}">
+ <s:isUserInRole role="admin">
+ <d:invokeBody />
+ </s:isUserInRole>
+ </j:when>
+ <!-- if the security is disabled or the test passes -->
+ <j:otherwise>
+ <d:invokeBody />
+ </j:otherwise>
+ </j:choose>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/jobDeleteForm.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/jobDeleteForm.jelly
new file mode 100644
index 0000000..5b52e22
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/jobDeleteForm.jelly
@@ -0,0 +1,80 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Nikita Levyankov
+#
+#
+#************************************************************************** -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <script type="text/javascript">
+ function onDeleteClick() {
+ jQuery.ajax({
+ url: "${rootURL}/${it.url}api/json",
+ dataType: 'json',
+ cache: false,
+ success: function(data) {
+ jQuery('#confirmDialog').show();
+ jQuery('#buildInProgressDialog').hide();
+ jQuery('#cascadingChildrenPresentDiald').hide();
+ var cascadingChildren = data.cascadingChildrenNames;
+ if (cascadingChildren.length != 0) {
+ var jobList = jQuery("#jobList");
+ jobList.html("");
+ cascadingChildren.sort();
+ for (var i = 0; i &lt; cascadingChildren.length; i++) {
+ jobList.append("<li>" + cascadingChildren[i] + "</li>");
+ }
+ jQuery('#confirmDialog').hide();
+ jQuery('#buildInProgressDialog').hide();
+ jQuery('#cascadingChildrenPresentDiald').show();
+ } else{
+ if(data.lastBuild.length != 0){
+ var lastBuildUrl = data.lastBuild.url + "api/json";
+ jQuery.ajax({
+ url: lastBuildUrl,
+ dataType: 'json',
+ cache: false,
+ success: function(buildData) {
+ if(buildData.building){
+ jQuery('#confirmDialog').hide();
+ jQuery('#cascadingChildrenPresentDiald').hide();
+ jQuery('#buildInProgressDialog').show();
+ }
+ }
+ });
+ }
+ }
+ }
+ });
+ onLinkClick("question");
+ }
+ </script>
+ <div>
+ <form method="post" action="doDelete" id="deleteForm">
+ <div id="confirmDialog">
+ <h4>${%deleteMsg}</h4>
+ <input type="submit" class="yes" value="${%Yes}"/>
+ <input type="button" class="no" value="${%No}"/>
+ </div>
+ <div id="cascadingChildrenPresentDiald" class="deleteJobDialog" style="display:none">
+ <h4>${%cannotDeleteBecauseOfChildrenMsg}</h4>
+ <ul id="jobList">
+ </ul>
+ <input type="button" class="no" value="${%Ok}" />
+ </div>
+ <div id="buildInProgressDialog" class="deleteJobDialog" style="display:none">
+ <h4>${%cannotDeleteBecauseBuildInProgressMsg}</h4>
+ <input type="button" class="no" value="${%Ok}" />
+ </div>
+ </form>
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/jobLink.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/jobLink.jelly
new file mode 100644
index 0000000..f4333c9
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/jobLink.jelly
@@ -0,0 +1,29 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Generates a link to a job.
+ <st:attribute name="job" type="hudson.model.Job" use="required">
+ Job object to be displayed.
+ </st:attribute>
+ </st:documentation>
+
+<img src="${imagesURL}/16x16/${job.buildStatusUrl}" alt="${job.iconColor.description}"/>
+<a href="${h.getRelativeLinkTo(job)}">${job.displayName}</a>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/jobpropertysummaries.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/jobpropertysummaries.jelly
new file mode 100644
index 0000000..5945eee
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/jobpropertysummaries.jelly
@@ -0,0 +1,25 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Erik Ramfelt
+#
+#
+#************************************************************************** -->
+
+
+<!-- display permalinks of the page -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler">
+ <!-- give properties a chance to contribute summary item -->
+ <j:forEach var="p" items="${it.properties.values()}">
+ <st:include page="summary.jelly" from="${p}" optional="true" it="${p}" />
+ </j:forEach>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/label.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/label.jelly
new file mode 100644
index 0000000..0b9471d
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/label.jelly
@@ -0,0 +1,27 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:st="jelly:stapler">
+ <st:documentation>
+ Puts the input field for allowing an user to limit this installer to a certain label.
+ Meant to be used from config.jelly of ToolInstaller subypes.
+ </st:documentation>
+ <f:entry title="${%Label}" field="label" help="/help/tools/help-label.html">
+ <!-- XXX could use Hudson.getLabels and make a combo box -->
+ <f:textbox/>
+ </f:entry>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/layout.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/layout.jelly
new file mode 100644
index 0000000..1cd0987
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/layout.jelly
@@ -0,0 +1,303 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Nikita Levyankov
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:i="jelly:fmt">
+ <st:documentation>
+ Outer-most tag for a normal (non-AJAX) HTML rendering.
+ This is used with nested &lt;header>, &lt;side-panel>, and &lt;main-panel>
+ to form Hudson's basic HTML layout.
+
+ <st:attribute name="title" use="required">
+ Title of the HTML page. Rendered into &lt;title> tag.
+ </st:attribute>
+ <st:attribute name="norefresh">
+ If non-null, auto refresh is disabled on this page.
+ This is necessary for pages that include forms.
+ </st:attribute>
+ <st:attribute name="css" deprecated="true">
+ specify path that starts from "/" for loading additional CSS stylesheet.
+ path is interprted as relative to the context root. e.g.,
+
+ {noformat}&lt;l:layout css="/plugin/mysuperplugin/css/myneatstyle.css">{noformat}
+
+ This was originally added to allow plugins to load their stylesheets, but
+ *the use of thie attribute is discouraged now.*
+ plugins should now do so by inserting &lt;style> elements and/or &lt;script> elements
+ in &lt;l:header/> tag.
+ </st:attribute>
+ <st:attribute name="permission">
+ If given, this page is only made available to users that has the specified permission.
+ (The permission will be checked against the "it" object.)
+ </st:attribute>
+ </st:documentation>
+ <st:header name="Expires" value="0" />
+ <st:header name="X-Hudson-Theme" value="default" />
+ <st:contentType value="text/html;charset=UTF-8" />
+ <!-- The path starts with a "/" character but does not end with a "/" character. -->
+ <j:set var="rootURL" value="${request.contextPath}" />
+ <j:new var="h" className="hudson.Functions" /><!-- instead of JSP functions -->
+ <j:new var="cu" className="hudson.util.CascadingUtil"/> <!-- Utility for cascading functionality -->
+ <j:set var="_" value="${h.configureAutoRefresh(request, response, attrs.norefresh!=null)}"/>
+ <!--
+ load static resources from the path dedicated to a specific version.
+ This "/static/VERSION/abc/def.ghi" path is interpreted by stapler to be
+ the same thing as "/abc/def.ghi", but this avoids the stale cache
+ problem when the user upgrades to new Hudson. Stapler also sets a long
+ future expiration dates for such static resources.
+ -->
+ <j:set var="resURL" value="${rootURL}${h.resourcePath}" />
+ <j:set var="imagesURL" value="${rootURL}${h.resourcePath}/images" />
+ <html>
+ <head>
+ ${h.checkPermission(it,permission)}
+
+ <title>${h.appendIfNotNull(title, ' [Hudson]', 'Hudson')}</title>
+ <link rel="stylesheet" href="${resURL}/css/style.css?${h.version}" type="text/css" />
+ <link rel="stylesheet" href="${resURL}/css/color.css" type="text/css" />
+ <j:if test="${attrs.css!=null}">
+ <link rel="stylesheet" href="${rootURL}${attrs.css}" type="text/css" />
+ </j:if>
+ <link rel="shortcut icon" href="${resURL}/favicon.ico" type="image/vnd.microsoft.icon" />
+
+ <!-- are we running as an unit test? -->
+ <script>var isRunAsTest=${h.isUnitTest}; var rootURL="${rootURL}";</script>
+
+ <script src="${resURL}/scripts/prototype-1.7.js" type="text/javascript"></script>
+ <script src="${resURL}/scripts/ext-prototype.js" type="text/javascript"></script>
+ <script src="${resURL}/scripts/behavior.js" type="text/javascript"></script>
+ <script src="${resURL}/scripts/sortable.js" type="text/javascript"></script>
+ <script src="${resURL}/scripts/jquery-1.6.4.min.js" type="text/javascript"></script>
+ <script src="${resURL}/scripts/jquery.blockUI-2.39.js" type="text/javascript"></script>
+
+ <!-- To use the debug version of YUI, set the system property 'debug.YUI' to true -->
+ <!--
+ <j:set var="yuiSuffix" value="${h.yuiSuffix}" />
+ -->
+ <j:set var="yuiSuffix" value="min" />
+ <l:yui module="yahoo" />
+ <l:yui module="dom" />
+ <l:yui module="event" />
+ <j:if test="${h.yuiSuffix=='debug'}">
+ <l:yui module="logger" />
+ </j:if>
+ <l:yui module="animation" />
+ <l:yui module="dragdrop" />
+ <l:yui module="container" />
+ <l:yui module="connection" />
+ <l:yui module="datasource" />
+ <l:yui module="autocomplete" />
+ <l:yui module="menu" />
+ <l:yui module="element"/>
+ <l:yui module="button" />
+ <!--l:yui module="editor" suffix="-beta" /-->
+
+ <script src="${resURL}/scripts/hudson-behavior.js?${h.version}" type="text/javascript"></script>
+ <script src="${resURL}/scripts/cascading.js?${h.version}" type="text/javascript"></script>
+ <script>
+ crumb.init("${h.getCrumbRequestField()}", "${h.getCrumb(request)}");
+ </script>
+
+ <link rel="stylesheet" href="${resURL}/scripts/yui/container/assets/container.css" type="text/css"/>
+ <link rel="stylesheet" href="${resURL}/scripts/yui/assets/skins/sam/skin.css" type="text/css" />
+ <link rel="stylesheet" href="${resURL}/scripts/yui/container/assets/skins/sam/container.css" type="text/css"/>
+ <link rel="stylesheet" href="${resURL}/scripts/yui/button/assets/skins/sam/button.css" type="text/css" />
+ <link rel="stylesheet" href="${resURL}/scripts/yui/menu/assets/skins/sam/menu.css" type="text/css" />
+ <!--link rel="stylesheet" href="${resURL}/scripts/yui/editor/assets/skins/sam/editor.css" type="text/css" /-->
+
+ <link rel="search" type="application/opensearchdescription+xml" href="${rootURL}/opensearch.xml" title="Hudson" />
+ <meta name="ROBOTS" content="INDEX,NOFOLLOW" />
+ <j:set var="mode" value="header" />
+ <d:invokeBody />
+ <j:forEach var="pd" items="${h.pageDecorators}">
+ <st:include it="${pd}" page="header.jelly" optional="true" />
+ </j:forEach>
+ </head>
+ <body class="yui-skin-sam">
+ <!-- for accessibility, skip the entire navigation bar and etc and go straight to the head of the content -->
+ <a href="#skip2content" class="skiplink">Skip to content</a>
+ <table id="main-table" style="min-width:225px; background-image:url(${imagesURL}/header-bar.png); background-repeat:repeat-x"
+ border="0" cellspacing="0" cellpadding="0" height="100%" width="100%" bgcolor="#FAF7FD">
+ <tr>
+ <!-- Left Panel -->
+ <td id="side-panel" height="100%" width="25%" style="min-width:225px">
+ <!-- Hudson Logo -->
+ <div>
+ <a href="${rootURL}/"><img src="${imagesURL}/hudson-logo.png" alt="Hudson logo" /></a>
+ </div>
+
+ <!-- Left Navigation Bar -->
+ <div id="navigation" style="padding:5px">
+ <j:set var="mode" value="side-panel" />
+ <d:invokeBody />
+
+ <!-- add YUI logger if debugging YUI -->
+ <j:if test="${h.yuiSuffix=='debug'}">
+ <div id="yui-logreader" style="margin-top:1em"/>
+ <script>
+ Behaviour.addLoadEvent(function(){
+ var logReader = new YAHOO.widget.LogReader("yui-logreader");
+ logReader.collapse();
+ });
+ </script>
+ </j:if>
+ </div>
+ </td>
+ <!-- Right Panel -->
+ <td height="100%">
+ <div style="margin-bottom:1px;">
+
+ <table id="header" cellpadding="0" cellspacing="0" width="100%" border="0">
+ <tr>
+ <td colspan="2">
+ <table cellpadding="2" cellspacing="3" width="100%" border="0">
+ <tr>
+
+ <td style="vertical-align: middle; text-align: right; padding-right: 1em;">
+ <!-- search box -->
+ <j:set var="searchURL" value="${h.searchURL}"/>
+ <form action="${searchURL}" method="get" style="position:relative;" class="no-json" name="search">
+ <!-- this div determines the minimum width -->
+ <div id="search-box-minWidth"/>
+ <!-- this div is used to calculate the width of the text box -->
+ <div id="search-box-sizer"/>
+ <div id="searchform">
+ <input name="q" value="search" id="search-box" class="has-default-text defaulted" />
+ <st:nbsp />
+ <a href="${%searchBox.url}">
+ <img src="${imagesURL}/16x16/help.png" alt="help for search" />
+ </a>
+ <div id="search-box-completion" />
+ <script>createSearchBox("${searchURL}");</script>
+ </div>
+ </form>
+ </td>
+ <td id="login-field">
+ <span>
+ <!-- login field -->
+ <j:if test="${app.useSecurity}">
+ <st:nbsp/>
+ <j:choose>
+ <j:when test="${!h.isAnonymous()}">
+ <span style="white-space:nowrap">
+ <a href="${rootURL}/user/${app.authentication.name}">
+ <b>${app.authentication.name}</b>
+ </a>
+ <j:if test="${app.securityRealm.canLogOut()}">
+ |
+ <a href="${rootURL}/logout">
+ <b>${%logout}</b>
+ </a>
+ </j:if>
+ </span>
+ </j:when>
+ <j:otherwise>
+ <st:include it="${app.securityRealm}" page="loginLink.jelly" />
+ </j:otherwise>
+ </j:choose>
+ </j:if>
+ </span>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr id="top-nav" >
+ <td id="left-top-nav">
+ <j:forEach var="anc" items="${request.ancestors}">
+ <j:if test="${h.isModel(anc.object)}">
+ <j:if test="${anc.prev.url!=anc.url}">
+ <j:if test="${anc.prev!=null}">
+ <j:whitespace> &#187; </j:whitespace>
+ </j:if>
+ <a href="${anc.url}/">
+ ${anc.object.displayName}
+ </a>
+ </j:if>
+ </j:if>
+ </j:forEach>
+ </td>
+ <td id="right-top-nav">
+ <j:if test="${attrs.norefresh==null}">
+ <span class="smallfont">
+ <j:choose>
+ <j:when test="${h.isAutoRefresh(request)}">
+ <a href="?auto_refresh=false">${%DISABLE AUTO REFRESH}</a>
+ </j:when>
+ <j:otherwise>
+ <a href="?auto_refresh=true">${%ENABLE AUTO REFRESH}</a>
+ </j:otherwise>
+ </j:choose>
+ </span>
+ </j:if>
+ </td>
+ </tr>
+
+ </table>
+ </div>
+
+ <div style=" height:100%">
+ <img src="${imagesURL}/top-left-round.png" style="float:left"/>
+ <div style="margin-left:25; height:25; background-image:url(${imagesURL}/spacer.png); background-repeat:repeat-x" />
+ <div id="main-panel-container" style=" background-color:#FFFFFF; padding-left: 10px; height:100%">
+ <table width="95%" height="100%" border="0">
+ <tr>
+ <td id="global-messages" width="100%">
+ <j:forEach var="globalMessage" items="${app.globalMessages}">
+ <j:if test="${globalMessage.enabled}">
+ <div class="global-message">
+ <st:include page="detail.jelly" it="${globalMessage}"/>
+ </div>
+ </j:if>
+ </j:forEach>
+ </td>
+ </tr>
+ <tr>
+ <td id="main-panel" width="100%" height="100%">
+ <j:set var="mode" value="main-panel" />
+ <d:invokeBody/>
+ </td>
+ </tr>
+ </table>
+ <br style="clear:both"/>
+ </div>
+
+ </div>
+
+ </td>
+ </tr>
+
+ <tr>
+ <table width="100%">
+ <tr>
+ <td id="footer">
+ <span style="padding-right:2em; color:gray">
+ ${%Page generated}:
+ <i:formatDate value="${h.getCurrentTime()}" type="both" dateStyle="medium" timeStyle="medium"/>
+ </span>
+ <a href="http://hudson-ci.org/">Hudson ver. ${h.version}</a>
+ </td>
+ </tr>
+ </table>
+ <j:forEach var="pd" items="${h.pageDecorators}">
+ <st:include it="${pd}" page="footer.jelly" optional="true" />
+ </j:forEach>
+ </tr>
+ </table>
+ </body>
+ </html>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/legend.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/legend.jelly
new file mode 100644
index 0000000..0809f13
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/legend.jelly
@@ -0,0 +1,80 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe,
+#
+#
+#************************************************************************** -->
+
+
+<!-- show the icon legend -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form">
+ <l:layout>
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <table cellpadding="5">
+ <tr><td>
+ <img src="images/48x48/grey.png" alt=""/>
+ ${%grey}
+ </td></tr>
+ <tr><td>
+ <img src="images/48x48/grey_anime.gif" alt=""/>
+ ${%grey_anime}
+ </td></tr>
+ <tr><td>
+ <img src="images/48x48/blue.png" alt=""/>
+ ${%blue}
+ </td></tr>
+ <tr><td>
+ <img src="images/48x48/blue_anime.gif" alt=""/>
+ ${%blue_anime}
+ </td></tr>
+ <tr><td>
+ <img src="images/48x48/yellow.png" alt=""/>
+ ${%yellow}
+ </td></tr>
+ <tr><td>
+ <img src="images/48x48/yellow_anime.gif" alt=""/>
+ ${%yellow_anime}
+ </td></tr>
+ <tr><td>
+ <img src="images/48x48/red.png" alt=""/>
+ ${%red}
+ </td></tr>
+ <tr><td>
+ <img src="images/48x48/red_anime.gif" alt=""/>
+ ${%red_anime}
+ </td></tr>
+ <tr><td>
+ <img src="images/48x48/health-80plus.png" alt=""/>
+ ${%health-81plus}
+ </td></tr>
+ <tr><td>
+ <img src="images/48x48/health-60to79.png" alt=""/>
+ ${%health-61to80}
+ </td></tr>
+ <tr><td>
+ <img src="images/48x48/health-40to59.png" alt=""/>
+ ${%health-41to60}
+ </td></tr>
+ <tr><td>
+ <img src="images/48x48/health-20to39.png" alt=""/>
+ ${%health-21to40}
+ </td></tr>
+ <tr><td>
+ <img src="images/48x48/health-00to19.png" alt=""/>
+ ${%health-00to20}
+ </td></tr>
+ </table>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/levels.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/levels.jelly
new file mode 100644
index 0000000..499488d
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/levels.jelly
@@ -0,0 +1,68 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Show form to adjust log levels
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+<l:layout title="Log Levels">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <h1>
+ ${%Logger Configuration}
+ <t:help href="${%url}" />
+ </h1>
+ <table class="sortable pane bigtable" style="width:auto" id="logLevels">
+ <tr>
+ <th>${%Name}</th>
+ <th>${%Level}</th>
+ </tr>
+ <j:invokeStatic var="lm" className="java.util.logging.LogManager" method="getLogManager"/>
+ <j:forEach var="name" items="${h.loggerNames}">
+ <j:set var="logger" value="${lm.getLogger(name)}"/>
+ <j:if test="${logger.level != null}">
+ <tr>
+ <td>${name}</td>
+ <td>${logger.level}</td>
+ </tr>
+ </j:if>
+ </j:forEach>
+ </table>
+ <p>${%defaultLoggerMsg}</p>
+ <h2>${%Adjust Levels}</h2>
+ <form action="configLogger" method="post" name="configLogger">
+ ${%Name}: <input type="text" name="name" width="40" />
+ ${%Level}:
+ <select name="level">
+ <option>inherit</option>
+ <option>off</option>
+ <option>severe</option>
+ <option>warning</option>
+ <option>info</option>
+ <option>config</option>
+ <option>fine</option>
+ <option>finer</option>
+ <option>finest</option>
+ <option>all</option>
+ </select>
+ <st:nbsp/>
+ <f:submit value="${%Submit}"/>
+ </form>
+ </l:main-panel>
+</l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/link.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/link.jelly
new file mode 100644
index 0000000..6450dd4
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/link.jelly
@@ -0,0 +1,31 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Permalink to a build from a project page
+
+ 'job' must be bound to the parent job scope.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:p="/lib/hudson/project">
+ <j:set var="b" value="${it.resolve(job)}"/>
+ <j:if test="${b!=null}">
+ <li>
+ <a href="${it.id}/">${%format(it.displayName,b.displayName,b.timestampString)}</a>
+ </li>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/list.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/list.jelly
new file mode 100644
index 0000000..4bdaae6
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/list.jelly
@@ -0,0 +1,52 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Tom Huybrechts, Yahoo!, Inc.
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define"
+ xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <table class="pane sortable" id="testresult">
+ <tr>
+ <td class="pane-header">${%Build}</td>
+ <td class="pane-header">${%Description}</td>
+ <td class="pane-header" style="width:5em">${%Duration}</td>
+ <td class="pane-header" style="width:5em">${%Fail}</td>
+ <td class="pane-header" style="width:5em">${%Skip}</td>
+ <td class="pane-header" style="width:5em">${%Total}</td>
+ </tr>
+ <tbody>
+ <j:forEach var="b" items="${it.owner.parent.builds}" begin="${start}" end="${end}">
+ <j:set var="p" value="${it.getResultInBuild(b)}"/>
+ <j:if test="${p != null}">
+ <tr>
+ <td class="pane">
+ <a href="${app.rootUrl}${b.url}testReport${p.url}">${b.fullDisplayName}</a>
+ <st:nbsp/>
+ <j:forEach var="badge" items="${p.testActions}">
+ <st:include it="${badge}" page="badge.jelly" optional="true"/>
+ </j:forEach>
+ </td>
+ <td class="pane" style="text-align:right"><j:out value="${p.description!=null ? app.markupFormatter.translate(p.description) : ''}"/></td>
+ <td class="pane" style="text-align:right" data="${p.duration}">${p.durationString}</td>
+ <td class="pane" style="text-align:right">${p.failCount}</td>
+ <td class="pane" style="text-align:right">${p.skipCount}</td>
+ <td class="pane" style="text-align:right">${p.totalCount}</td>
+ </tr>
+ </j:if>
+ </j:forEach>
+ </tbody>
+ </table>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/listScmBrowsers.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/listScmBrowsers.jelly
new file mode 100644
index 0000000..53fd295
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/listScmBrowsers.jelly
@@ -0,0 +1,37 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ List browser SCMs
+ <st:attribute name="name" use="required">
+ form field name.
+ </st:attribute>
+ </st:documentation>
+ <f:dropdownList name="${name}" title="${%Repository browser}" help="/help/scm-browsers/list.html">
+ <f:dropdownListBlock value="auto" title="(${%Auto})" />
+ <j:set var="currentBrowser" value="${scm.browser}"/>
+ <j:forEach var="descriptor" items="${scmd.browserDescriptors}" varStatus="loop">
+ <f:dropdownListBlock value="${loop.index}" title="${descriptor.displayName}"
+ selected="${currentBrowser.descriptor==descriptor}" staplerClass="${descriptor.clazz.name}">
+ <j:set var="browser" value="${currentBrowser.descriptor==descriptor ? currentBrowser : null}"/><!-- for compatibility -->
+ <j:set var="instance" value="${browser}" />
+ <st:include from="${descriptor}" page="${descriptor.configPage}"/>
+ </f:dropdownListBlock>
+ </j:forEach>
+ </f:dropdownList>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/load-statistics.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/load-statistics.jelly
new file mode 100644
index 0000000..25ea369
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/load-statistics.jelly
@@ -0,0 +1,26 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="${it.displayName} Load Statistics">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <st:include page="main.jelly" from="${it.loadStatistics}" />
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/log.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/log.jelly
new file mode 100644
index 0000000..a123186
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/log.jelly
@@ -0,0 +1,32 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="${it.displayName} log" secured="true">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <l:isAdmin>
+ <pre id="out" />
+ <div id="spinner">
+ <img src="${imagesURL}/spinner.gif" alt=""/>
+ </div>
+ <t:progressiveText href="logText/progressiveHtml" idref="out" spinner="spinner" />
+ </l:isAdmin>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/logKeep.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/logKeep.jelly
new file mode 100644
index 0000000..e42218a
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/logKeep.jelly
@@ -0,0 +1,33 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Displays the toggle button to keep/don't-keep the log file.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <j:if test="${it.parent.logRotator!=null}">
+ <form method="get" action="toggleLogKeep" style="margin-top:1em">
+ <j:if test="${it.keepLog}">
+ <f:submit value="${%Don't keep this build forever}" />
+ </j:if>
+ <j:if test="${!it.keepLog}">
+ <f:submit value="${%Keep this build forever}" />
+ </j:if>
+ </form>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/login.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/login.jelly
new file mode 100644
index 0000000..6b9e9f6
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/login.jelly
@@ -0,0 +1,66 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <l:layout norefresh="true">
+ <l:hasPermission permission="${app.READ}">
+ <st:include page="sidepanel.jelly" />
+ </l:hasPermission>
+ <l:main-panel>
+ <div style="margin: 2em;">
+ <!-- login form -->
+ <form name="login" action="${rootURL}/${it.securityRealm.authenticationGatewayUrl}" method="post" style="text-size:smaller">
+ <table>
+ <tr>
+ <td>${%User}:</td>
+ <td><input type="text" name="j_username" id="j_username" /></td>
+ </tr>
+ <tr>
+ <td>${%Password}:</td>
+ <td><input type="password" name="j_password" /></td>
+ </tr>
+ <j:if test="${app.security.name()=='SECURED'}">
+ <!-- remember me service only available for Spring Security -->
+ <tr>
+ <td align="right"><input id="remember_me" type="checkbox" name="remember_me" /></td>
+ <td><label for="remember_me">${%Remember me on this computer}</label></td>
+ </tr>
+ </j:if>
+ </table>
+ <input type="hidden" name="from" value="${request.getParameter('from')}" />
+ <f:submit value="${%login}" />
+ <script>
+ $('j_username').focus();
+ </script>
+ </form>
+
+ <j:forEach var="fls" items="${it.getFederatedLoginServices()}">
+ <div>
+ <st:include page="loginFragment.jelly" it="${fls}"/>
+ </div>
+ </j:forEach>
+
+ <j:if test="${it.securityRealm.allowsSignup()}">
+ <div style="margin-top:2em">
+ ${%signUp}
+ </div>
+ </j:if>
+ </div>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/loginDialog.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/loginDialog.jelly
new file mode 100644
index 0000000..71f8542
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/loginDialog.jelly
@@ -0,0 +1,80 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Winston Prakash
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <style type="text/css">
+ #loginForm input {
+ width: 150px;
+ }
+ </style>
+ <div style="margin: 2em;">
+ <!-- login form -->
+ <form id="loginForm" style="text-size:smaller">
+ <table >
+ <tr>
+ <td>${%User}:</td>
+ <td>
+ <input type="text" name="j_username" id="j_username" />
+ </td>
+ </tr>
+ <tr>
+ <td >${%Password}:</td>
+ <td>
+ <input type="password" name="j_password" id="j_password"/>
+ </td>
+ </tr>
+ <j:if test="${app.security.name()=='SECURED'}">
+ <!-- remember me service only available for Spring Security -->
+ <tr>
+ <td align="right">
+ <input style="width:10px" id="remember_me" type="checkbox" name="remember_me" />
+ </td>
+ <td>
+ <label for="remember_me">${%Remember me on this computer}</label>
+ </td>
+ </tr>
+ </j:if>
+ </table>
+ <input type="hidden" name="from" value="${submitFrom}" />
+ <input style="width:75px" type="button" id="loginButton" value="${%Login}" />
+ <input style="margin-left:10px; width:75px" type="button" id="cancelButton" value="${%Cancel}" />
+
+ </form>
+
+ <div id="loginError">
+ ${%Invalid login information. Please try again.}
+ </div>
+
+ <div id="loginMsg">
+ ${%Logging in...}
+ </div>
+
+
+ <j:forEach var="fls" items="${app.getFederatedLoginServices()}">
+ <div>
+ <st:include page="loginFragment.jelly" it="${fls}"/>
+ </div>
+ </j:forEach>
+
+ <j:if test="${app.securityRealm.allowsSignup()}">
+ <div style="margin-top:2em">
+ ${%signUp(rootURL)}
+ </div>
+ </j:if>
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/loginError.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/loginError.jelly
new file mode 100644
index 0000000..adab65b
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/loginError.jelly
@@ -0,0 +1,51 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Matthew R. Harrah
+#
+#
+#************************************************************************** -->
+
+
+<!-- report a login error -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:choose>
+ <j:new var="h" className="hudson.Functions" />
+ <j:when test="${app.isUseSecurity() and h.isAnonymous()}">
+ <!--
+ The only time the error message makes sense is when Jenkins is protected and the user failed to authenticate.
+ If the user accidentally comes to this page (by back button, etc), redirect away to prevent a confusion.
+ -->
+ <st:statusCode value="401" />
+ <l:layout title="${%Login Error}">
+ <l:hasPermission permission="${app.READ}">
+ <st:include page="sidepanel.jelly" />
+ </l:hasPermission>
+ <l:main-panel>
+ <div style="margin: 2em; text-align:center; color:red; font-weight:bold">
+ ${%Invalid login information. Please try again.}
+ <br/>
+ <a href="login?from=${request.session.getAttribute('from')}">${%Try again}</a>
+ </div>
+ <div align="middle">
+ <div style="margin-top:2em; color:gray; width:20em">
+ ${%If you are a system administrator and suspect this to be a configuration problem, see the server console output for more details.}
+ </div>
+ </div>
+ </l:main-panel>
+ </l:layout>
+ </j:when>
+ <j:otherwise>
+ <st:redirect url="." />
+ </j:otherwise>
+ </j:choose>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/loginLink.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/loginLink.jelly
new file mode 100644
index 0000000..0c9a606
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/loginLink.jelly
@@ -0,0 +1,116 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Inc., Winston Prakash
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler">
+ <j:invokeStatic var="fromEncoded" className="java.net.URLEncoder" method="encode">
+
+ <j:arg value="${if (request.session.attribute('from')!=null) request.session.getAttribute('from'); else if (request.getParameter('from')!=null) request.getParameter('from'); else if (request.requestURI=='/loginError' || request.requestURI=='/login') '/'; else request.requestURI;}"/>
+ <j:arg value="UTF-8"/>
+
+ </j:invokeStatic>
+
+ <j:set var="from" value="${if (request.session.attribute('from')!=null) request.session.getAttribute('from'); else if (request.getParameter('from')!=null) request.getParameter('from'); else if (request.requestURI=='/loginError' || request.requestURI=='/login') '/'; else request.requestURI;}" />
+
+
+ <script type="text/javascript">
+
+ function showLoginDialog(){
+ jQuery.blockUI({
+ message: jQuery('#loginDialog'),
+ css: {
+ width: '350px'
+ },
+ title: 'Confirmation'
+ });
+ jQuery('j_username').focus();
+ }
+
+ function submitForm(){
+ jQuery('#loginMsg').show();
+ jQuery('#loginError').hide();
+ var dataString = jQuery("#loginForm").serialize();
+ jQuery.ajax({
+ type: 'POST',
+ url: "${rootURL}/${app.securityRealm.authenticationGatewayUrl}",
+ data: dataString,
+ success: function(){
+ window.location.href="${h.jsStringEscape(from)}";
+ },
+ error: function(){
+ jQuery('#loginError').show();
+ jQuery('#loginMsg').hide();
+ },
+ dataType: "html"
+ });
+ }
+
+ jQuery(document).ready(function() {
+
+ jQuery('#j_username').keypress(function(e){
+ if(e.which == 13){
+ submitForm();
+ }
+ });
+
+ jQuery('#j_password').keypress(function(e){
+ if(e.which == 13){
+ submitForm();
+ }
+ });
+
+
+ jQuery('#loginButton').click(function() {
+ submitForm();
+ });
+
+
+ jQuery('#cancelButton').click(function() {
+ jQuery.unblockUI();
+ jQuery('#j_username').attr({value:""});
+ jQuery('#j_password').attr({value:""});
+ jQuery('#loginError').hide();
+ jQuery('#loginMsg').hide();
+ return false;
+ });
+
+ });
+
+ </script>
+
+ <!-- We cannot use ajax in case of container based authentication (LegacySecurityRealm)
+ because of the HTTP Status 400 - Invalid direct reference to form login page -->
+ <j:choose>
+ <j:when test="${app.securityRealm.loginUrl=='loginEntry'}">
+ <a style="color:inherit" href="${rootURL}/${app.securityRealm.loginUrl}?from=${from}">
+ <b>${%login}</b>
+ </a>
+ </j:when>
+ <j:otherwise>
+ <a href="${rootURL}/${app.securityRealm.loginUrl}?from=${fromEncoded}"
+ onclick="showLoginDialog(); return false;">
+ <b>${%login}</b>
+ </a>
+ </j:otherwise>
+ </j:choose>
+
+ <div id="loginDialog" style="display:none; cursor: default">
+ <j:set var="submitFrom" value="${from}" />
+ <st:include page="loginDialog.jelly" />
+ </div>
+
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/main-panel.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/main-panel.jelly
new file mode 100644
index 0000000..feff94c
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/main-panel.jelly
@@ -0,0 +1,28 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define">
+ <st:documentation>
+ Generates the body as the main content part of a Hudson page.
+ </st:documentation>
+
+ <j:if test="${mode=='main-panel'}">
+ <a name="skip2content" />
+ <d:invokeBody />
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/main.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/main.jelly
new file mode 100644
index 0000000..178a123
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/main.jelly
@@ -0,0 +1,69 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <j:choose>
+ <j:when test="${app.slaveAgentPort==-1}">
+ <div class="error">
+ ${%slaveAgentPort.disabled}
+ <l:isAdmin><a href="${rootURL}/configure">${%configure.link.text}</a>.</l:isAdmin>
+ </div>
+ </j:when>
+ <j:when test="${it.offline and !it.temporarilyOffline}">
+ <l:isAdmin><!-- TODO: we need a permission to launch a slave -->
+ <p>
+ ${%Connect slave to Hudson one of these ways:}
+ </p>
+ <ul>
+ <li>
+ <p>
+ <a href="slave-agent.jnlp" id="jnlp-link">
+ <img src="${imagesURL}/webstart.gif" alt="${%launch agent}" />
+ </a>
+ ${%Launch agent from browser on slave}
+ </p>
+ </li>
+ <li>
+ <p>
+ ${%Run from slave command line:}
+ </p>
+ <pre>javaws ${h.inferHudsonURL(request)}${it.url}slave-agent.jnlp</pre>
+ </li>
+ <li>
+ <p>
+ ${%Or if the slave is headless:}
+ </p>
+ <pre>java -jar <a href="${rootURL}/jnlpJars/slave.jar">slave.jar</a> -jnlpUrl ${h.inferHudsonURL(request)}${it.url}slave-agent.jnlp</pre>
+ </li>
+ </ul>
+ <!--
+ <p>
+ <a href="custom-jnlp" style="margin-left:3em">
+ (tweak launch parameters)
+ </a>
+ </p>
+ -->
+ </l:isAdmin>
+ </j:when>
+ <j:otherwise>
+ <p>
+ ${%Connected via JNLP agent.}
+ </p>
+ </j:otherwise>
+ </j:choose>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/manage.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/manage.jelly
new file mode 100644
index 0000000..2afc8d1
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/manage.jelly
@@ -0,0 +1,131 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2012 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe, Stephen Connolly, Winston Prakash
+#
+#************************************************************************** -->
+
+<!--
+ Entrance to the configuration page
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <l:layout title="${%Manage Hudson}" xmlns:local="local" permission="${app.ADMINISTER}">
+ <d:taglib uri="local">
+ <!-- table to show a map -->
+ <d:tag name="feature">
+ <t:summary icon="${icon}"
+ href="${href}" iconOnly="true">
+ <div class="link">
+ <a href="${href}">${title}</a>
+ </div>
+ <div style="color:gray; text-decoration:none;">
+ <d:invokeBody />
+ </div>
+ </t:summary>
+ </d:tag>
+ </d:taglib>
+
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <h1>${%Manage Hudson}</h1>
+ <j:if test="${it.checkURIEncodingEnabled}">
+ <script>
+ var url='checkURIEncoding';
+ var params='value=\u57f7\u4e8b';
+ var checkAjax=new Ajax.Updater(
+ 'message', url,
+ {
+ method: 'get', parameters: params
+ }
+ );
+ </script>
+ <span id="message"></span>
+ </j:if>
+
+ <j:forEach var="am" items="${app.administrativeMonitors}">
+ <j:if test="${am.isActivated() and am.isEnabled()}">
+ <st:include page="message.jelly" it="${am}" />
+ </j:if>
+ </j:forEach>
+
+ <st:include page="downgrade.jelly" />
+
+ <table style="padding-left: 2em;" id="management-links">
+
+ <local:feature icon="secure.png" href="securityManager" title="${%Configure Security}">
+ ${%Configure Authentication and Authorization Stretegy for Hudson Security.}
+ </local:feature>
+
+ <local:feature icon="setting.png" href="configure" title="${%Configure System}">
+ ${%Configure global settings and paths.}
+ </local:feature>
+
+ <local:feature icon="refresh.png" href="reload" title="${%Reload Configuration from Disk}">
+ ${%Discard all the loaded data in memory and reload everything from file system.}
+ ${%Useful when you modified config files directly on disk.}
+ </local:feature>
+
+ <local:feature icon="plugin.png" href="pluginManager/" title="${%Manage Plugins}">
+ ${%Add, remove, disable or enable plugins that can extend the functionality of Hudson.}
+ <j:if test="${it.updateCenter.hasUpdates()}">
+ <span style="color:red; font-weight:bold">(${%updates available})</span>
+ </j:if>
+ </local:feature>
+
+ <local:feature icon="computer.png" href="systemInfo" title="${%System Information}">
+ ${%Displays various environmental information to assist trouble-shooting.}
+ </local:feature>
+
+ <local:feature icon="clipboard.png" href="log" title="${%System Log}">
+ ${%SystemLogText}
+ </local:feature>
+
+ <local:feature icon="monitor.png" href="load-statistics" title="${%Load Statistics}">
+ ${%LoadStatisticsText}
+ </local:feature>
+
+ <local:feature icon="terminal.png" href="cli" title="${%Hudson CLI}">
+ ${%HudsonCliText}
+ </local:feature>
+
+ <local:feature icon="notepad.png" href="script" title="${%Script Console}">
+ ${%Executes arbitrary script for administration/trouble-shooting/diagnostics.}
+ </local:feature>
+
+ <local:feature icon="network.png" href="computer/" title="${%Manage Nodes}">
+ ${%Add, remove, control and monitor the various nodes that Hudson runs jobs on.}
+ </local:feature>
+
+ <!-- TODO: replace all the hard-coded ones with the standard extension point -->
+ <j:forEach var="m" items="${it.managementLinks}">
+ <j:if test="${m.iconFileName!=null}">
+ <local:feature icon="${m.iconFileName}" href="${m.urlName}" title="${m.displayName}">
+ <j:out value="${m.description}"/>
+ </local:feature>
+ </j:if>
+ </j:forEach>
+
+ <j:choose>
+ <j:when test="${it.quietingDown}">
+ <local:feature icon="system-log-out.png" href="cancelQuietDown" title="${%Cancel Shutdown}"/>
+ </j:when>
+ <j:otherwise>
+ <local:feature icon="system-log-out.png" href="quietDown" title="${%Prepare for Shutdown}">
+ ${%Stops executing new builds, so that the system can be eventually shut down safely.}
+ </local:feature>
+ </j:otherwise>
+ </j:choose>
+
+ </table>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/markOffline.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/markOffline.jelly
new file mode 100644
index 0000000..16b489e
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/markOffline.jelly
@@ -0,0 +1,37 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe, Stephen Connolly, Tom Huybrechts
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout title="${%title(it.displayName)}">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <l:isAdmin>
+ <h2>${%title(it.displayName)}</h2>
+ <p>
+ ${%blurb}
+ </p>
+ <form method="post" action="toggleOffline">
+ <f:textarea name="offlineMessage" />
+ <p>
+ <f:submit value="${%submit}" />
+ </p>
+ </form>
+ </l:isAdmin>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/matrix.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/matrix.jelly
new file mode 100644
index 0000000..27a4b79
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/matrix.jelly
@@ -0,0 +1,97 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Yahoo! Inc.
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Generate configuration matrix and invoke body with 'p' as the instance of T
+ (of Layouter<T>)
+
+ Used by Matrix* classes
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project">
+ <st:documentation>
+ Generate configuration matrix and invoke body with 'p' as the instance of T
+ (of Layouter&lt;T>)
+
+ <st:attribute name="autoRefresh">
+ If specified, the content of the matrix will be automatically updated via AJAX.
+ (This happens by requesting URL "./ajaxMatrix", so the caller needs "ajaxMatrix.jelly"
+ to serve this request.)
+ </st:attribute>
+ </st:documentation>
+
+ <j:set var="o" value="${it.layouter}"/>
+ <div id='matrix'>
+ <j:choose>
+ <!-- Optimized case when there's only one dimension to the axis (or zero dimension) -->
+ <j:when test="${empty(o.x) and empty(o.y)}">
+ <h2>${%Configurations}</h2>
+ <j:forEach var="p" items="${o.rows[0][0]}">
+ <d:invokeBody />
+ <st:nbsp />
+ </j:forEach>
+ </j:when>
+ <j:otherwise>
+ <h2>${%Configuration Matrix}</h2>
+ <table border="1" class="middle-align center-align">
+ <!-- X-axis -->
+ <j:forEach var="x" items="${o.x}" varStatus="loop">
+ <tr>
+ <!-- space for Y-axis -->
+ <j:if test="${!empty(o.y)}">
+ <td colspan="${size(o.y)}" />
+ </j:if>
+ <j:forEach begin="1" end="${o.repeatX(loop.index)}">
+ <j:forEach var="v" items="${x.values}">
+ <td colspan="${o.width(loop.index)}">${v}</td>
+ </j:forEach>
+ </j:forEach>
+ </tr>
+ </j:forEach>
+
+ <!-- Y-axis -->
+ <j:forEach var="r" items="${o.rows}">
+ <tr>
+ <j:forEach var="y" items="${o.y}" varStatus="loop">
+ <j:if test="${r.drawYHeader(loop.index)!=null}">
+ <td rowspan="${o.height(loop.index)}">${r.drawYHeader(loop.index)}</td>
+ </j:if>
+ </j:forEach>
+
+ <j:forEach var="c" items="${r}">
+ <td>
+ <j:choose>
+ <j:forEach var="p" items="${c}">
+ <div>
+ <d:invokeBody />
+ </div>
+ </j:forEach>
+ </j:choose>
+ </td>
+ </j:forEach>
+ </tr>
+ </j:forEach>
+ </table>
+ </j:otherwise>
+ </j:choose>
+ <j:if test="${ajax==null and attrs.autoRefresh and !h.isAutoRefresh(request)}">
+ <script defer="defer">
+ refreshPart('matrix',"./ajaxMatrix");
+ </script>
+ </j:if>
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/message.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/message.jelly
new file mode 100644
index 0000000..c9dc463
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/message.jelly
@@ -0,0 +1,24 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <div class="error">
+ <j:out value="${it.message}"/>
+ <a href="${it.url}/">${%See the log for more details}</a>.
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/myViewTabs.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/myViewTabs.jelly
new file mode 100644
index 0000000..74745bb
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/myViewTabs.jelly
@@ -0,0 +1,30 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <!-- view tab bar -->
+ <l:tabBar>
+ <j:forEach var="v" items="${views}">
+ <l:tab name="${v.viewName}" active="${v==currentView}" href="${rootURL}/${v.url}" />
+ </j:forEach>
+ <j:if test="${currentView.hasPermission(currentView.CREATE)}">
+ <l:tab name="+" href="${rootURL}/${currentView.owner.url}newView" active="false"
+ title="${%New View}" />
+ </j:if>
+ </l:tabBar>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/nested.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/nested.jelly
new file mode 100644
index 0000000..6c1cfa8
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/nested.jelly
@@ -0,0 +1,34 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Used to display indented nested portion of the form
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ <st:attribute name="isPropertyOverridden">
+ if present and true - the column will be highlight as overridden cascading property.
+ </st:attribute>
+ </st:documentation>
+ <tr>
+ <td colspan="2" class="${attrs.isPropertyOverridden? 'modified' :'original'}"/>
+ <td colspan="2">
+ <d:invokeBody />
+ </td>
+ </tr>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/new.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/new.jelly
new file mode 100644
index 0000000..0244048
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/new.jelly
@@ -0,0 +1,35 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ "New slave" page.
+
+ The flow of this is:
+
+ new.jelly -> ComputerSet.doCreateItem -> _new2.jelly -> ComputerSet.doDoCreateItem
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form">
+ <l:layout norefresh="true" permission="${app.ADMINISTER}">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <j:invokeStatic var="slaves" className="hudson.slaves.NodeDescriptor" method="allInstantiable" />
+ <n:form nameTitle="${%Node name}" copyTitle="${%Copy Existing Node}" copyNames="${it._slaveNames}"
+ descriptors="${slaves}" checkUrl="computer/checkName" xmlns:n="/lib/hudson/newFromList" />
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/newInstanceDetail.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/newInstanceDetail.jelly
new file mode 100644
index 0000000..24ff82b
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/newInstanceDetail.jelly
@@ -0,0 +1,21 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<div>
+ ${%detail}
+</div>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/newJob.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/newJob.jelly
new file mode 100644
index 0000000..0ebacad
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/newJob.jelly
@@ -0,0 +1,32 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, id:cactusman
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ "New Project" page.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form">
+ <j:getStatic var="permission" className="hudson.model.Item" field="CREATE"/>
+ <l:layout norefresh="true" permission="${permission}" title="${%New Job}">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <j:invokeStatic var="jobs" className="hudson.model.Items" method="all" />
+ <n:form nameTitle="${%Job name}" copyTitle="${%Copy existing job}" copyNames="${app.topLevelItemNames}"
+ descriptors="${jobs}" checkUrl="checkJobName" xmlns:n="/lib/hudson/newFromList" />
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/newJobDetail.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/newJobDetail.jelly
new file mode 100644
index 0000000..9371e72
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/newJobDetail.jelly
@@ -0,0 +1,21 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, id:cactusman
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<div>
+ ${%body}
+</div>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/newView.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/newView.jelly
new file mode 100644
index 0000000..53666e8
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/newView.jelly
@@ -0,0 +1,19 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<st:include from="${app}" page="newView.jelly" xmlns:st="jelly:stapler" />
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/newViewDetail.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/newViewDetail.jelly
new file mode 100644
index 0000000..4c7c3ba
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/newViewDetail.jelly
@@ -0,0 +1,21 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<div>
+ <b>Experimental:</b> show hierarchical views
+</div>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/noJob.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/noJob.jelly
new file mode 100644
index 0000000..4bb0bef
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/noJob.jelly
@@ -0,0 +1,36 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core">
+ <style type="text/css">
+ #noJobDiv {
+ padding: 10px;
+ text-align: center;
+ border-width: 0px 1px 1px;
+ border-style: none solid solid;
+ border-color: #BBBBBB;
+ }
+ </style>
+<div id="noJobDiv">
+ ${%description_1}
+ <j:if test="${it.hasPermission(it.CONFIGURE)}">
+ <j:set var="configLink" value="${rootURL}/${it.viewUrl}configure"/>
+ ${%description_2(configLink)}
+ </j:if>
+</div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/noPrincipal.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/noPrincipal.jelly
new file mode 100644
index 0000000..3cd8f6b
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/noPrincipal.jelly
@@ -0,0 +1,29 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe
+#
+#
+#************************************************************************** -->
+
+
+<!-- there seems to be no authentication -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <l:layout>
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <div style="margin: 2em; color:red; font-weight:bold">
+ ${%blurb}
+ </div>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/noWorkspace.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/noWorkspace.jelly
new file mode 100644
index 0000000..c7f0d45
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/noWorkspace.jelly
@@ -0,0 +1,53 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, id:cactusman
+#
+#
+#************************************************************************** -->
+
+
+<!-- tell user that there's no workspace yet -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout>
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <h1><img src="${imagesURL}/48x48/error.png" alt=""/>${%Error: no workspace}</h1>
+ <j:choose>
+ <j:when test="${it.lastBuild==null}">
+ <p>
+ ${%A project won't have any workspace until at least one build is performed.}
+ </p>
+ </j:when>
+ <j:otherwise>
+ <p>
+ ${%There's no workspace for this project. Possible reasons are:}
+ </p>
+ <ol>
+ <li>
+ ${%The project was renamed recently and no build was done under the new name.}
+ </li>
+ <li>
+ ${%The slave this project has run on for the last time was removed.}
+ </li>
+ <li>
+ ${%li3(it.workspace.local)}
+ </li>
+ </ol>
+ </j:otherwise>
+ </j:choose>
+ <p>
+ ${%text(rootURL,it.url)}
+ </p>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/node.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/node.jelly
new file mode 100644
index 0000000..4c63bec
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/node.jelly
@@ -0,0 +1,32 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Displays a link to a node.
+ <st:attribute name="value" use="required" type="Node"/>
+ </st:documentation>
+ <j:choose>
+ <j:when test="${value!=null and value!=app}">
+ <a href="${rootURL}/computer/${value.nodeName}">${value.nodeName}</a>
+ </j:when>
+ <j:otherwise>
+ ${%master}
+ </j:otherwise>
+ </j:choose>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/nodepropertysummaries.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/nodepropertysummaries.jelly
new file mode 100644
index 0000000..5e71e59
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/nodepropertysummaries.jelly
@@ -0,0 +1,28 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Erik Ramfelt
+#
+#
+#************************************************************************** -->
+
+
+<!-- display permalinks of the page -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler">
+ <!-- give properties a chance to contribute summary item -->
+ <j:forEach var="p" items="${app.globalNodeProperties}">
+ <st:include page="summary.jelly" from="${p}" optional="true" it="${p}" />
+ </j:forEach>
+ <j:forEach var="p" items="${it.node.nodeProperties}">
+ <st:include page="summary.jelly" from="${p}" optional="true" it="${p}" />
+ </j:forEach>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/opensearch.xml.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/opensearch.xml.jelly
new file mode 100644
index 0000000..03dc50e
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/opensearch.xml.jelly
@@ -0,0 +1,34 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ OpenSearch description for using search box from browsers
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define"
+><st:contentType value="application/xml;charset=UTF-8"
+/><OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+ <j:new var="h" className="hudson.Functions" /><!-- instead of JSP functions -->
+ <j:set var="rootURL" value="${h.inferHudsonURL(request)}"/>
+ <ShortName>Hudson</ShortName>
+ <Description>Hudson at ${rootURL}</Description>
+ <InputEncoding>UTF-8</InputEncoding>
+ <Image width="16" height="16">data:image/x-icon,%00%00%01%00%03%0000%00%00%01%00%20%00%A8%25%00%006%00%00%00%20%20%00%00%01%00%20%00%A8%10%00%00%DE%25%00%00%10%10%00%00%01%00%20%00h%04%00%00%866%00%00(%00%00%000%00%00%00%60%00%00%00%01%00%20%00%00%00%00%00%00%24%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00000%FD%14%14%14%FDsss%FDbbb%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FDNNN%FD%12%12%12%FD666%FD%5D%5D%5D%FD%5D%5D%5D%FD%5E%5E%5E%FD%5D%5D%5D%FDMMM%FD%1F%1F%1F%FD%97%97%97%FD___%FD222%FD.))%FD%8Brr%FD%8Arr%FD%8Arr%FDB88%FDwww%FD%D4%CB%CB%FD%8Brr%FD%8Arr%FD%8Aqq%FD%8Brr%FD%23%1F%1F%FDZZZ%FD%93%93%93%FD%17%17%17%FD'''%FD%5D%5D%5D%FDXXX%FD%5C%5C%5C%FD%5D%5D%5D%FD%5E%5E%5E%FD%82%82%82%FD%3A%3A%3A%FDQQQ%FDccc%FD%12%12%12%FD%8C%8C%8C%FDggg%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FDWWW%FD%14%14%14%FD%23%23%23%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FDLLL%FD777%FD%9B%9B%9B%FDiii%FD222%FD.))%FD%8Aqq%FD%8Arr%FD%8Arr%FD)%24%24%FD%15%15%15%FD%C9%C9%C9%FD%B4%A3%A3%FD%8Arr%FD%8Arr%FD%8Aqq%FD%23%1F%1F%FDZZZ%FD%9B%9B%9B%FDHHH%FD%14%14%14%FDSSS%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%60%60%60%FD%8A%8A%8A%FD%18%18%18%FD%CE%CE%CE%FD%A1%A1%A1%FD%13%13%13%FD%84%84%84%FDnnn%FD%5D%5D%5D%FD%5D%5D%5D%FD%5E%5E%5E%FD%5D%5D%5D%FD%5D%5D%5D%FD%5E%5E%5E%FD%5D%5D%5D%FD%5D%5D%5D%FD%5D%5D%5D%FD%19%19%19%FD%14%14%14%FDZZZ%FD%5D%5D%5D%FD%5D%5D%5D%FD%5D%5D%5D%FD777%FDQQQ%FD%9C%9C%9C%FDxxx%FD222%FD.))%FD%8Brr%FD%8Brr%FD%84mm%FD%15%15%15%FD%13%13%13%FD666%FD%EC%EA%EA%FD%8Evv%FD%8Bqq%FD%8Brr%FD%23%1F%1F%FDZZZ%FD%9C%9C%9C%FDyyy%FD%13%13%13%FD555%FD%5D%5D%5D%FD%5E%5E%5E%FD%89%89%89%FD%9C%9C%9C%FDnnn%FDccc%FD%FF%FF%FF%FD%D3%D3%D3%FD%13%13%13%FDrrr%FDwww%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%25%25%25%FD%13%13%13%FDQQQ%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%1C%1C%1C%FDjjj%FD%9C%9C%9C%FDrrr%FD222%FD0**%FD%8Bqq%FD%8Brr%FDn%5B%5B%FD%12%12%12%FDfff%FD%13%13%13%FD%82%82%82%FD%B1%A0%A0%FD%8Brr%FD%88oo%FD%1C%1A%1A%FDZZZ%FD%9C%9C%9C%FD%98%98%98%FD%13%13%13%FD%1E%1E%1E%FD%5E%5E%5E%FDlll%FD%9B%9B%9B%FD%83%83%83%FD'''%FD%DC%DC%DC%FD%FF%FF%FF%FD%F5%F5%F5%FD%12%12%12%FDnnn%FD%7C%7C%7C%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%25%25%25%FD%16%16%16%FD%5C%5C%5C%FD%5E%5E%5E%FD%5E%5E%5E%FDLLL%FD%13%13%13%FD%82%82%82%FD%98%98%98%FD%60%60%60%FD222%FDI%3E%3E%FD%8Brr%FD%8Arr%FD%4066%FD%1B%1B%1B%FD%E4%E4%E4%FD%24%24%24%FD!!!%FD%CA%C1%C1%FD%8Arr%FD%84ll%FD%13%13%13%FDZZZ%FD%9B%9B%9B%FD%98%98%98%FD%13%13%13%FD%1A%1A%1A%FD%5E%5E%5E%FD%8F%8F%8F%FD%7D%7D%7D%FD%1C%1C%1C%FDttt%FD%FE%FE%FE%FD%FE%FE%FE%FD%F5%F5%F5%FD%13%13%13%FDXXX%FD%86%86%86%FD%5D%5D%5D%FD%5D%5D%5D%FD%5E%5E%5E%FD%5D%5D%5D%FD%5D%5D%5D%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%24%24%24%FD)))%FD%5D%5D%5D%FD%5D%5D%5D%FD%5E%5E%5E%FD---%FD%1D%1D%1D%FD%97%97%97%FD%83%83%83%FD%5D%5D%5D%FD%23%23%23%FDcRR%FD%8Brr%FD%7Bee%FD%16%15%15%FDbbb%FD%FF%FF%FF%FDQQQ%FD%12%12%12%FD%95%8C%8C%FD%8Bqq%FD%84ll%FD%13%13%13%FDZZZ%FD%9C%9C%9C%FD%98%98%98%FD%13%13%13%FD%1A%1A%1A%FDfff%FDxxx%FD%18%18%18%FD%1E%1E%1E%FD%E6%E6%E6%FD%FE%FE%FE%FD%FF%FF%FF%FD%F9%F9%F9%FD%20%20%20%FDWWW%FD%86%86%86%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%17%17%17%FD%3E%3E%3E%FD%5E%5E%5E%FD%5E%5E%5E%FDYYY%FD%16%16%16%FDSSS%FD%9C%9C%9C%FDmmm%FDRRR%FD%13%13%13%FD%7Cff%FD%8Brr%FDK%3F%3F%FD%13%13%13%FD%BE%BE%BE%FD%FF%FF%FF%FD%8C%8C%8C%FD%12%12%12%FDRII%FD%8Arr%FD%7Fii%FD%13%13%13%FDiii%FD%9B%9B%9B%FD%98%98%98%FD%13%13%13%FD%1A%1A%1A%FDvvv%FD111%FD%14%14%14%FD%AB%AB%AB%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD666%FD%3D%3D%3D%FD%8B%8B%8B%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5C%5C%5C%FD%1E%1E%1E%FD%5B%5B%5B%FD%5E%5E%5E%FD%5E%5E%5E%FD%40%40%40%FD%16%16%16%FD%92%92%92%FD%94%94%94%FD___%FD999%FD%1E%1B%1B%FD%8Arr%FD%83ll%FD%1A%18%18%FD111%FD%D6%D6%D6%FD%FE%FE%FE%FD%CA%CA%CA%FD%12%12%12%FD!%1E%1E%FD%8Aqq%FD%5BLL%FD%19%19%19%FD%95%95%95%FD%9C%9C%9C%FD%98%98%98%FD%12%12%12%FD%1A%1A%1A%FDccc%FD%13%13%13%FDyyy%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD666%FD%3D%3D%3D%FD%92%92%92%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FDSSS%FD%40%40%40%FD%5E%5E%5E%FD%5D%5D%5D%FD%5D%5D%5D%FD%22%22%22%FDJJJ%FD%9C%9C%9C%FD%7F%7F%7F%FD%5E%5E%5E%FD!!!%FDH%3D%3D%FD%8Brr%FDWII%FD%13%13%13%FD%A4%A4%A4%FDWWW%FD%EF%EF%EF%FD%F5%F5%F5%FD%20%20%20%FD%13%13%13%FD%88oo%FD0**%FD%3C%3C%3C%FD%9C%9C%9C%FD%9C%9C%9C%FD%98%98%98%FD%13%13%13%FD%1C%1C%1C%FD444%FDZZZ%FD%FB%FB%FB%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FDMMM%FD%26%26%26%FD%92%92%92%FD%5D%5D%5D%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FDZZZ%FD%5C%5C%5C%FD%5E%5E%5E%FD%5E%5E%5E%FDLLL%FD%12%12%12%FD%84%84%84%FD%9B%9B%9B%FDjjj%FDRRR%FD%13%13%13%FDwbb%FD%89pp%FD%22%1F%1F%FDhhh%FD%FC%FC%FC%FD%F8%F8%F8%FD%FF%FF%FF%FD%F2%F2%F2%FD)))%FD%13%13%13%FDzdd%FD%12%12%12%FDLLL%FD%9B%9B%9B%FD%9C%9C%9C%FD%8B%8B%8B%FD%13%13%13%FD%14%14%14%FD%3B%3B%3B%FD%F3%F3%F3%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%7F%7F%7F%FD%1C%1C%1C%FD%93%93%93%FD___%FD%5D%5D%5D%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%2F%2F%2F%FD%3C%3C%3C%FD%9B%9B%9B%FD%92%92%92%FD%5E%5E%5E%FD888%FD.((%FD%8Aqq%FDZKK%FDAAA%FD%F8%F8%F8%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%F2%F2%F2%FD%40%40%40%FD%12%12%12%FDNBB%FD%16%16%16%FD%5D%5D%5D%FD%99%99%99%FD%9B%9B%9B%FDYYY%FD%13%13%13%FD)))%FD%D8%D8%D8%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%B1%B1%B1%FD%13%13%13%FD%92%92%92%FD___%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5D%5D%5D%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FDWWW%FD%15%15%15%FDwww%FD%9C%9C%9C%FD%8E%8E%8E%FD%5D%5D%5D%FD%1E%1E%1E%FD%5DMM%FDr%5E%5E%FD%22%22%22%FD%DC%DC%DC%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%F2%F2%F2%FD%3A%3A%3A%FD%13%13%13%FD%24%20%20%FD777%FD%5E%5E%5E%FD%93%93%93%FD%9C%9C%9C%FD(((%FD%13%13%13%FD%B2%B2%B2%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%E4%E4%E4%FD%13%13%13%FDwww%FD___%FD%5D%5D%5D%FD%5E%5E%5E%FD%5D%5D%5D%FDnnn%FDlll%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%3A%3A%3A%FD---%FD%9B%9B%9B%FD%9C%9C%9C%FD%8E%8E%8E%FDDDD%FD%19%17%17%FDvbb%FD%22%20%20%FD%BE%BE%BE%FD%FE%FE%FE%FD%FF%FF%FF%FDooo%FD%FC%FC%FC%FD%FF%FF%FF%FD%B1%B1%B1%FD%26%26%26%FD%13%13%13%FD%1E%1E%1E%FD%5B%5B%5B%FD%5E%5E%5E%FD%81%81%81%FDhhh%FD%13%13%13%FD444%FD%F9%F9%F9%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FD%FD%FD%FD%2C%2C%2C%FDggg%FD%88%88%88%FDppp%FDccc%FDzzz%FD%85%85%85%FDddd%FD%5D%5D%5D%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FD%1E%1E%1E%FD%5E%5E%5E%FD%9B%9B%9B%FD%9B%9B%9B%FD%81%81%81%FD%1D%1D%1D%FD%3D44%FD%3B77%FD___%FD%C0%C0%C0%FD%FE%FE%FE%FD%FA%FA%FA%FD%D3%D3%D3%FD%FE%FE%FE%FD%CE%CE%CE%FDnnn%FD%17%17%17%FD%13%13%13%FDLLL%FD%5D%5D%5D%FD%5D%5D%5D%FD%5E%5E%5E%FD444%FD%12%12%12%FD%8C%8C%8C%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%83%83%83%FD%16%16%16%FDjjj%FDttt%FDAAA%FD%1E%1E%1E%FDzzz%FD%5E%5E%5E%FD%5D%5D%5D%FD%5E%5E%5E%FD%5D%5D%5D%FD%5D%5D%5D%FDUUU%FD%15%15%15%FD%8C%8C%8C%FD%9C%9C%9C%FD%9C%9C%9C%FD___%FD%13%13%13%FDWUU%FDppp%FDrrr%FDqqq%FD%82%82%82%FDrrr%FDyyy%FD%87%87%87%FDuuu%FDXXX%FD%12%12%12%FD%23%23'%FD%5D%5D%5D%FD%5D%5D%5D%FD%5D%5D%5D%FD%3D%3D%3D%FD%26%26%26%FD%90%90%90%FD%F9%F9%F9%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%F1%F1%F1%FD'''%FD%13%13%13%FD%13%13%13%FD%13%13%13%FDYYY%FD%8C%8C%8C%FDwww%FDwww%FDwww%FDrrr%FD%5E%5E%5E%FD%3C%3C%3C%FD%3F%3F%3F%FD%9B%9B%9B%FD%9C%9C%9C%FD%95%95%95%FD%1F%1F%1F%FD%14%14%14%FD555%FDYYY%FDXXX%FD999%FDAAA%FDJJJ%FDTTT%FDCCC%FD---%FD%18%18)%FD%26%26%83%FD%16%16(%FDHHH%FDXXX%FD777%FD%85%85%85%FD%ED%ED%ED%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%C4%C4%C4%FD%5C%5C%5C%FD%13%13%13%FD%1C%1C%1C%FDppp%FD%91%91%91%FD%9B%9B%9B%FD%9B%9B%9B%FD%9B%9B%9B%FD%9B%9B%9B%FD%80%80%80%FD)))%FDppp%FD%9B%9B%9B%FD%9B%9B%9B%FD%5C%5Ch%FD%23%23s%FD%20%20a%FD%1B%1BD%FD%17%17%2C%FD%13%13%14%FD%19%197%FD%25%25%7F%FD%23%23s%FD%17%17.%FD%1C%1CG%FD%20%20a%FD%2C%2C%A6%FD**%96%FD%13%13%14%FDAAA%FDsss%FD%EA%EA%EA%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%E7%E7%E7%FD%7F%7F%7F%FDRRR%FDDDD%FD***%FD%20%20%20%FD%15%15%15%FD%15%15%15%FDUUU%FD%1C%1C%1C%FD%97%97%97%FD%9C%9C%9C%FD%90%90%90%FD%23%23J%FDQQ%BA%FDYY%BE%FD..%AD%FD%25%25~%FD%19%19%3A%FD%18%183%FDqq%C7%FD%B1%B1%E0%FDII%A7%FD..%AD%FD..%AD%FD..%AD%FD%26%26%80%FD%15%15%16%FD%98%98%98%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%F5%F5%F5%FD%E9%E9%E9%FD%B8%B8%B8%FD***%FD%13%13%13%FDsss%FD%98%98%98%FD%40%40%40%FDAA%7F%FD%EF%EF%F9%FD%D2%D2%ED%FD**%98%FD%23%23o%FD%22%238%FD%84%85%A1%FD%CF%CF%D1%FD%BB%BB%C0%FD%24%25G%FD%22%22%3B%FD%22%22e%FD))%92%FD))%93%FD%15%15%23%FD%B4%B4%B4%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%BA%BA%BA%FD%13%13%13%FD%2B%2B%2B%FD%3A%3A%3A%FDVVq%FD%E5%E5%F4%FD%E9%E9%E9%FDQQh%FD%1C%1D%23%FD%5Ee%86%FD%A6%B4%F4%FD%AC%BC%FE%FD%9C%A9%E5%FD%96%A3%DC%FDbi%8C%FDyyy%FD%E6%E6%E6%FD%B0%B0%B0%FD%83%83%83%FD%B2%B2%B2%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%8A%8A%8A%FD%13%13%13%FD%17%17%17%FD%84%84%84%FD%96%96%96%FD%25%25%25%FDkny%FD%9D%AB%E8%FD%AC%BB%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BB%FF%FD%AD%BC%FF%FD%82%8D%BE%FD'''%FD%FD%FD%FD%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%8E%8E%8E%FD%81%81%81%FD%C3%C3%C3%FD%EB%EB%EB%FDCCC%FD%E9%ED%FF%FD%AC%BC%FF%FD%AD%BB%FE%FD%AD%BC%FF%FD%AC%BC%FF%FD%AD%BC%FE%FD%AD%BC%FF%FD%A0%AE%EC%FD%1F%20%25%FD%BC%BC%BC%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FDFFF%FD%E9%ED%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AC%BC%FE%FD%AD%BB%FE%FD%AD%BC%FF%FDkt%9B%FD777%FD%F2%F2%F2%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%1C%1C%1C%FD%DE%E4%FF%FD%AD%BC%FF%FD%AD%BB%FF%FD%AC%BC%FF%FD%AD%BC%FF%FD%AD%BB%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%A9%B7%F9%FD%22%23*%FDnnn%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%1C%1C%1C%FD%D9%E0%FE%FD%AD%BC%FF%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BC%FF%FD%AD%BB%FE%FD%AD%BC%FF%FD%AA%B9%FB%FD%86%92%C4%FD%18%18%1A%FD%13%13%13%FDyyy%FD%E9%E9%E9%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%CD%CD%CD%FD555%FD%D9%E0%FF%FD%AC%BB%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AB%B9%FC%FD%89%95%C8%FDU%5Bx%FD%23%25%2C%FD%15%15%15%FD%1A%1A%1A%FD%1A%1A%1A%FD%19%19%19%FD%23%23%23%FD%A4%A4%A4%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%81%81%81%FD%88%89%8B%FD%BB%C7%FF%FD%AC%BC%FF%FD%AC%BB%FF%FD%A9%B7%F8%FD%40DW%FD---%FDrrr%FD%AD%AD%AD%FD%E9%E9%E9%FD%F3%F6%FF%FD%FD%FD%FF%FD%FA%FA%FA%FDRRR%FD%1B%1B%1B%FD%D4%D4%D4%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD888%FD%B7%BF%E0%FD%AD%BC%FF%FD%AD%BC%FF%FD%AC%BB%FE%FDNSm%FD999%FD%D6%D8%E4%FD%D8%DF%FF%FD%C6%D0%FF%FD%B3%C1%FE%FD%AD%BC%FF%FD%B8%C5%FF%FD%DD%E3%FE%FD%EA%EB%EC%FD444%FDCCC%FD%F7%F7%F7%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%D1%D1%D1%FD%3A%3DJ%FD%AE%BD%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%84%8F%C0%FDQRR%FD%C5%CC%EC%FD%B0%BE%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%C6%D0%FE%FD%B9%BA%BA%FD%12%12%12%FD%9F%9F%9F%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%8F%8F%8F%FDlu%9C%FD%AC%BB%FF%FD%AC%BC%FF%FD%A5%B4%F3%FDx%7C%90%FD%BB%C7%FC%FD%AC%BC%FF%FD%AD%BB%FE%FD%AC%BC%FF%FD%AD%BC%FF%FD%AC%BB%FF%FD%AC%BB%FF%FD%AC%BB%FF%FD%AC%BB%FE%FD%AC%BC%FF%FD%DA%E1%FE%FDLLL%FD%84%84%84%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%F9%F9%F9%FDOR%5C%FD%A7%B5%F5%FD%AD%BC%FF%FD%AD%BB%FF%FD%9F%AD%E8%FD%AE%BC%FD%FD%AD%BB%FF%FD%AD%BC%FF%FD%AD%BB%FE%FD%AD%BC%FE%FD%AD%BC%FF%FD%AD%BB%FE%FD%AD%BB%FF%FD%AD%BC%FF%FD%AD%BB%FE%FD%AD%BC%FE%FD%AE%BD%FF%FD%AA%AC%B8%FDccc%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FD%FD%FD%FDiik%FD%8F%9B%D1%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BB%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%A9%B7%F9%FDqz%A3%FDEJ%60%FD%2C.9%FDJOg%FD%A8%B6%F7%FD%96%9E%C4%FDVVV%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%84%84%84%FDZa%80%FD%AD%BC%FF%FD%AD%BB%FF%FD%AC%BB%FF%FD%AD%BC%FF%FD%AC%BC%FF%FD%AC%BB%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AC%BB%FF%FD%AC%BC%FF%FD%A6%B4%F4%FD9%3DN%FD%3C%40R%FDX_%7D%FDlu%9C%FDINf%FD%81%8C%BC%FD%95%9E%C4%FD%2C%2C%2C%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%E5%E5%E5%FD%99%99%99%FDikq%FD)%2C6%FDir%98%FD%AD%BC%FF%FD%AC%BB%FF%FD%AD%BC%FE%FD%AD%BC%FF%FD%AC%BB%FF%FD%AD%BC%FE%FD%AD%BC%FF%FD%96%A2%DB%FD%A0%AE%EC%FD%AD%BC%FF%FD%7C%86%B4%FD%96%A3%DC%FD%AD%BC%FF%FD%AC%BC%FF%FD%AA%B8%FA%FD%96%A2%DB%FD%96%A3%DD%FD%86%92%C4%FD)))%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FDvvv%FD%3B%3EN%FD%A4%B3%F2%FD%A5%B2%ED%FD%7F%87%AD%FD~%88%B7%FD%A0%AD%E8%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BC%FE%FD%AD%BB%FE%FDT%5Bw%FD***%FD%15%15%16%FD%1A%1B%1F%FD36D%FD36D%FD%1C%1D!%FD%2C.9%FD%2C%2F%3A%FD!!!%FD%1A%1A%1B%FDiq%97%FDEEE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%DE%DE%DE%FD000%FD%C8%D0%F6%FD%AC%BB%FF%FD%88%8E%A7%FD%2C%2C%2C%FD*-7%FD%8F%9B%D1%FD%AC%BB%FF%FD%AC%BB%FF%FD%AC%BC%FF%FD%AD%BB%FF%FD%5Bb%82%FDnnn%FDMMM%FD%1D%1D%1D%FD___%FDLLL%FD%2C%2C%2C%FDOOO%FD'''%FDhhh%FD%26'-%FDQWr%FD%87%87%87%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%B6%B6%B6%FD777%FD%CE%D7%FE%FD%A6%B3%EF%FDijl%FD)))%FD%D4%DA%F3%FD%AF%BD%FF%FD%AD%BC%FE%FD%AD%BC%FE%FD%AC%BC%FF%FD%AD%BC%FE%FD%92%9E%D6%FD%3B%3B%3B%FD%C8%C8%C8%FD%A1%A1%A1%FD%D9%D9%D9%FD%DC%DC%DC%FD%AF%AF%AF%FD%C6%C6%C6%FD%C4%C4%C4%FDXXX%FDW%5Ey%FD)*0%FD%C6%C6%C6%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%EF%EF%EF%FD%5C%5C%5C%FD000%FD%DA%DF%F6%FD%8F%97%B7%FDPPP%FD555%FD%FE%FE%FE%FD%F7%F8%FE%FD%D6%DE%FE%FD%AD%BB%FE%FD%AC%BB%FF%FD%AC%BB%FE%FD%AC%BB%FE%FD%84%8F%C1%FDs%7B%A1%FD%B7%BC%D5%FD%F5%F7%FE%FD%EF%F1%FB%FD%A4%A7%B3%FD%AE%B3%CB%FD%DC%DF%EB%FDdk%8A%FD%94%9C%C1%FD999%FD%F6%F6%F6%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FDqqq%FD%60%60%60%FDLLL%FDEEE%FD'''%FDNNN%FDXXX%FD%FF%FF%FF%FD%FF%FF%FF%FD%E5%EA%FF%FD%AD%BC%FF%FD%B5%C1%FB%FD%AA%AE%BE%FDil%7D%FD%9D%A7%D8%FD%AD%BC%FF%FD%AD%BC%FF%FD%A8%B7%F8%FD-0%3B%FD')2%FD%1D%1E%23%FD9%3CM%FD%AE%BD%FF%FDQS%5D%FD%EA%EA%EA%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FDuuu%FD%7B%7B%7B%FDxxx%FDqqq%FDrrr%FDVVV%FD%60%60%60%FD%FF%FF%FF%FD%EA%EE%FF%FD%B1%BF%FE%FD%AE%BC%FF%FD%AE%B1%BB%FD%12%12%12%FD333%FD%F3%F3%F4%FD%BC%C8%FE%FD%AD%BC%FF%FD%AD%BC%FF%FD%9D%AA%E6%FD%AD%BC%FF%FD%8C%98%CD%FD%26(1%FD%8E%97%BF%FD%DC%DC%DC%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FDmmm%FD%A6%A6%A6%FD%B3%B3%B3%FDqqq%FD%7D%7D%7D%FD___%FD999%FD%EB%EF%FE%FD%B0%BE%FE%FD%AC%BB%FE%FD%AD%BC%FE%FD%C6%D0%FB%FD%D1%D4%E2%FD%E2%E5%F3%FD%CD%D6%FE%FD%AE%BD%FE%FD%AC%BB%FE%FD%AC%BB%FE%FD%AC%BB%FE%FD%AC%BB%FE%FD%AB%BA%FC%FD25C%FD%90%91%95%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FDiii%FD%B4%B4%B4%FD%E5%E5%E5%FD%92%92%92%FD%7D%7D%7D%FDVVV%FD%16%16%16%FD%C2%C7%DE%FD%AD%BC%FF%FD%AB%BA%FB%FDio%87%FD%9A%A7%E2%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%A7%B5%F6%FDw%81%AD%FDox%A1%FD%7B%85%B2%FD%1C%1D!%FD%C0%C0%C0%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FDrrr%FD%88%88%88%FD%FF%FF%FF%FD%DC%DC%DC%FD%9E%9E%9E%FD%1C%1C%1C%FD%18%18%18%FD%8F%93%A3%FD%AD%BC%FF%FD%A9%B7%F5%FD%5D%5D%5D%FD%24%25*%FD%82%8C%BD%FD%AA%B9%FB%FD%AA%B9%FB%FD%AB%BA%FD%FD%AD%BC%FF%FDdl%8F%FD%23%24%2B%FDGLc%FDX%5Bk%FD%5D%5D%5D%FD!!!%FD%8F%8F%8F%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%CA%CA%CA%FD555%FD%E1%E1%E1%FD%DB%DB%DB%FD%F8%F8%F8%FDMMM%FD%13%13%13%FD%2C%2C%2C%FD%BF%C9%F4%FD%AC%BB%FD%FD%93%9B%C1%FDor%7D%FDKLP%FD456%FDRWn%FD%99%A5%DE%FD%8A%95%C9%FD8%3CL%FD%A1%AF%ED%FD%AA%B8%F9%FD%D6%DA%E9%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FDaaa%FD---%FDPPP%FD%C3%C3%C3%FD%DD%DD%DD%FD666%FD%13%13%13%FDoqw%FD%B5%C2%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AB%B9%FA%FD%AA%B8%F8%FD%AD%BC%FF%FD%AD%BC%FF%FD%A6%B5%F5%FDu~%A9%FD%B6%C2%F7%FDegq%FD%DF%DF%DF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FB%FB%FB%FD%9D%9D%9D%FDHHH%FD%22%22%22%FD%9D%9D%9D%FD%DE%DE%DE%FDzzz%FD!!!%FD%85%86%8A%FD%CA%D4%FF%FD%AC%BB%FF%FD%AE%BD%FE%FD%B9%C6%FF%FD%BF%CB%FF%FD%C7%D2%FE%FD%C7%D1%FF%FD%CE%D5%F3%FDyy%7B%FD999%FD%F4%F4%F4%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%EF%EF%EF%FDMMM%FDFFF%FD%BF%BF%BF%FD%BE%BE%BE%FDBBB%FDXXX%FD%89%89%8B%FD%BD%BE%BF%FD%92%92%92%FDDDD%FD%5E%5E%5E%FD%99%99%99%FD%88%88%88%FD%23%23%23%FD%B3%B3%B3%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%F5%F5%F5%FD%AF%AF%AF%FD%7B%7B%7B%FD777%FD%25%25%25%FD%16%16%16%FD%3D%3D%3D%FDjjj%FD%B2%B2%B2%FD%7F%7F%7F%FD%7C%7C%7C%FD%80%80%80%FDrrr%FD%BE%BE%BE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%FF%FF%FF%FD%FE%FE%FE%FD%FE%FE%FE%FD%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00(%00%00%00%20%00%00%00%40%00%00%00%01%00%20%00%00%00%00%00%00%10%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00...%FDYYY%FD%60%60%60%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%3B%3B%3B%FD%26%26%26%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD...%FD%87%87%87%FDAAA%FDMAA%FD%8Brr%FD~gg%FD%40%40%40%FD%C6%BA%BA%FD%8Brr%FD%8Brr%FDE%3B%3B%FDppp%FDGGG%FD444%FD%5B%5B%5B%FD%5D%5D%5D%FD%5E%5E%5E%FDrrr%FDRRR%FDfff%FD%60%60%60%FDhhh%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FDGGG%FD%16%16%16%FD%5C%5C%5C%FD%5E%5E%5E%FD%5C%5C%5C%FD%3C%3C%3C%FD%97%97%97%FDAAA%FDMAA%FD%8Brr%FDeTT%FD%13%13%13%FD%8D%8D%8D%FD%A3%8F%8F%FD%8Brr%FDE%3B%3B%FDppp%FD%7C%7C%7C%FD%18%18%18%FD%5B%5B%5B%FDccc%FD%88%88%88%FDVVV%FD%CF%CF%CF%FD%9A%9A%9A%FDRRR%FDooo%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FDQQQ%FD%13%13%13%FDWWW%FD%5E%5E%5E%FDFFF%FDRRR%FD%91%91%91%FDAAA%FDSEE%FD%8Brr%FDH%3D%3D%FDaaa%FD%19%19%19%FD%B4%AB%AB%FD%8Brr%FD%3C33%FDppp%FD%99%99%99%FD%13%13%13%FDKKK%FD%82%82%82%FDvvv%FDiii%FD%FF%FF%FF%FD%AA%AA%AA%FDDDD%FDwww%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FDPPP%FD%1E%1E%1E%FD%5E%5E%5E%FD%5E%5E%5E%FD***%FDlll%FD%7B%7B%7B%FD%3A%3A%3A%FDkYY%FD%84ll%FD%1C%1A%1A%FD%D6%D6%D6%FD666%FDtnn%FD%8Brr%FD6%2F%2F%FDppp%FD%99%99%99%FD%13%13%13%FDMMM%FDnnn%FD%1B%1B%1B%FD%DD%DD%DD%FD%FF%FF%FF%FD%BB%BB%BB%FD%3B%3B%3B%FDxxx%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FDGGG%FD555%FD%5E%5E%5E%FDWWW%FD%22%22%22%FD%97%97%97%FDeee%FD%20%20%20%FD%84ll%FDWII%FDFFF%FD%FF%FF%FF%FDnnn%FD3..%FD%8Brr%FD-((%FD%82%82%82%FD%99%99%99%FD%13%13%13%FDYYY%FD%20%20%20%FD%97%97%97%FD%FF%FF%FF%FD%FF%FF%FF%FD%C8%C8%C8%FD%2F%2F%2F%FD%80%80%80%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FDEEE%FDXXX%FD%5E%5E%5E%FD%3A%3A%3A%FDZZZ%FD%8C%8C%8C%FDRRR%FD%2F))%FD%89pp%FD%22%1F%1F%FD%8C%8C%8C%FD%BD%BD%BD%FD%A9%A9%A9%FD%14%14%14%FD%7Bee%FD)))%FD%9B%9B%9B%FD%99%99%99%FD%13%13%13%FD777%FDmmm%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%DE%DE%DE%FD%1F%1F%1F%FD%81%81%81%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5B%5B%5B%FD%5E%5E%5E%FD%5D%5D%5D%FD!!!%FD%91%91%91%FDvvv%FD999%FD%5ENN%FDbQQ%FDlll%FD%FC%FC%FC%FD%FD%FD%FD%FD%BC%BC%BC%FD%13%13%13%FDPCC%FD%3D%3D%3D%FD%9C%9C%9C%FD%88%88%88%FD%13%13%13%FDIII%FD%F9%F9%F9%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD'''%FD%82%82%82%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FDHHH%FDLLL%FD%9C%9C%9C%FDhhh%FD%26%24%24%FDzdd%FDKHH%FD%F6%F6%F6%FD%FF%FF%FF%FD%FF%FF%FF%FD%C4%C4%C4%FD%13%13%13%FD(%24%24%FDTTT%FD%97%97%97%FDWWW%FD'''%FD%EB%EB%EB%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FDZZZ%FDsss%FD___%FD%5E%5E%5E%FDvvv%FDggg%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FD(((%FD%88%88%88%FD%9C%9C%9C%FDOOO%FD%3F66%FD%3B66%FD%DE%DE%DE%FD%FF%FF%FF%FD%AC%AC%AC%FD%F9%F9%F9%FDyyy%FD%13%13%13%FD999%FD%5E%5E%5E%FDttt%FD%22%22%22%FD%84%84%84%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%9A%9A%9A%FD%40%40%40%FD%7F%7F%7F%FDKKK%FDbbb%FD%5E%5E%5E%FD%5E%5E%5E%FD%5E%5E%5E%FDYYY%FD111%FD%9B%9B%9B%FD%99%99%99%FD%22%22%22%FDROO%FDnnn%FD%8C%8C%8C%FD%A2%A2%A2%FD%A7%A7%A7%FD%96%96%96%FDEEE%FD%1A%1A%1C%FD%5C%5C%5C%FD%5D%5D%5D%FD%3C%3C%3C%FDSSS%FD%E7%E7%E7%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%F9%F9%F9%FD777%FD%13%13%13%FD'''%FD%90%90%90%FD%83%83%83%FD%83%83%83%FDxxx%FDEEE%FDfff%FD%9C%9C%9C%FDggk%FD%14%14%19%FD000%FDCCC%FD%2F%2F%3B%FD%3A%3AH%FD%3C%3C%3C%FD))%2C%FD!!a%FD%1C%1CI%FDKKK%FD___%FD%C1%C1%C1%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FA%FA%FA%FD%B0%B0%B0%FDXXX%FDYYY%FDPPP%FDBBB%FDJJJ%FD%3C%3C%3C%FD%93%93%93%FD%97%97%97%FD00p%FDPP%B9%FD((%8F%FD%1A%1A%3D%FD%25%25%5E%FD%80%80%CC%FD55%8F%FD%2C%2C%A3%FD--%AC%FD%18%18-%FD%96%96%96%FD%FE%FE%FE%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%F1%F1%F1%FD%B5%B5%B5%FD%1A%1A%1A%FDsss%FDGGO%FD%98%98%BF%FD%CE%CE%E4%FD!!e%FD%3FCk%FD%A0%A5%C8%FD%AB%AF%C1%FD%2F1J%FD%60%60%85%FD44%7F%FD%2B%2BE%FD%DD%DD%DD%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%8B%8B%8B%FD%15%15%15%FDddh%FD%A2%A2%A2%FDPQV%FD%83%8E%BF%FD%AC%BB%FE%FD%AD%BC%FF%FD%AD%BC%FF%FDX%5E%7D%FD%CA%CA%CA%FD%FD%FD%FD%FD%FD%FD%FD%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%AC%AC%AC%FD%CC%CC%CC%FD%C4%C4%C4%FD%A6%A9%B5%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%88%93%C6%FDnnn%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%BA%BA%BA%FD%A1%A5%B5%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FDBG%5B%FD%B9%B9%B9%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%A9%A9%A9%FD%9D%A2%B6%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%A5%B4%F4%FD%7B%85%B3%FD%2B-7%FD%22%22%22%FD%98%98%98%FD%F8%F8%F8%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FDppp%FD%C4%CB%EC%FD%AD%BC%FF%FD%AB%BA%FC%FDTZv%FDQRV%FD%84%84%84%FD%AE%AE%B3%FD%B4%B4%B5%FDbbb%FDeee%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%F9%F9%F9%FD_bl%FD%B0%BE%FF%FD%AD%BC%FF%FD%5Dd%84%FD%88%8A%92%FD%CC%D5%FE%FD%BA%C6%FF%FD%AD%BC%FF%FD%BA%C7%FF%FD%DE%E2%F6%FD%3F%3F%3F%FD%B2%B2%B2%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%BE%BE%BE%FDx%82%AF%FD%AD%BC%FF%FD%98%A4%DB%FD%98%9F%BC%FD%B0%BE%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AF%BD%FF%FD%B1%B4%C1%FD___%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FC%FC%FC%FDz%7D%8B%FD%AA%B9%FA%FD%AD%BC%FF%FD%A7%B5%F4%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AA%B9%FB%FD%95%A2%DB%FD%95%A1%DA%FD%B9%C6%FF%FDfgg%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%84%84%85%FD%97%A4%DE%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%97%A3%DD%FDAEY%FDEJa%FDAFZ%FD%97%A4%DE%FDQRU%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%B0%B0%B0%FDsw%87%FDU%5Cy%FD%AC%BB%FD%FD%AD%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%A1%AF%ED%FDjr%98%FD%7D%88%B6%FDr%7B%A4%FD%82%8D%BD%FD%8F%9B%D1%FDnw%9F%FD%80%8B%BA%FD%3E%40L%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%F0%F0%F0%FD%60%60b%FD%A9%B8%FA%FD%7C%82%99%FD-0%3B%FD%9A%A7%E0%FD%AD%BC%FF%FD%AD%BC%FF%FDmu%9D%FDVVV%FD!!!%FDCCC%FD)))%FD...%FDGGG%FDCGZ%FDZZ%5C%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%C0%C0%C0%FDvvz%FD%A6%B4%F0%FDIIJ%FD%AC%AE%B9%FD%C0%CC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%A1%AF%EC%FD%60ai%FD%AB%AB%AC%FD%E8%E8%E8%FD%D0%D0%D1%FD%D1%D1%D3%FD~~%80%FD%5Baz%FD%95%95%95%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%F3%F3%F3%FDTTT%FDSSS%FDWX%5C%FD999%FD%D9%D9%D9%FD%FE%FE%FF%FD%B9%C6%FF%FD%A9%B5%EA%FD%94%9B%BB%FD%A5%B3%ED%FD%A9%B7%F5%FD%A7%B0%D5%FDADQ%FD%40DT%FD%97%A2%D2%FDsu%81%FD%F3%F3%F3%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%EA%EA%EA%FDggg%FD%7F%7F%7F%FDrrr%FD%40%40%40%FD%DD%DD%DE%FD%CB%D5%FF%FD%AD%BC%FF%FD%99%9B%A5%FDddd%FD%E1%E5%FA%FD%AD%BC%FF%FD%A6%B5%F5%FD%AC%BA%FD%FDmv%9D%FDx~%96%FD%EF%EF%EF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%EA%EA%EA%FD%7D%7D%7D%FD%C5%C5%C5%FD%7B%7B%7B%FDDDD%FD%93%97%A7%FD%AD%BC%FF%FD%8E%99%C8%FD%A9%B6%F2%FD%BE%C9%FF%FD%AE%BC%FF%FD%AD%BC%FF%FD%AD%BC%FF%FD%92%9F%D6%FD%81%8C%BC%FD%3FAL%FD%E3%E3%E3%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%F3%F3%F3%FDaaa%FD%FE%FE%FE%FD%C2%C2%C2%FD%1D%1D%1D%FDUV%5D%FD%B0%BE%FF%FD%7C%81%98%FD%3FAJ%FDv%7F%AB%FD%82%8D%BC%FD%A9%B8%FA%FDKPi%FDah%8A%FD%8C%8F%9C%FDuuu%FD%CD%CD%CD%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%7D%7D%7D%FDhhh%FD%B3%B3%B3%FD%91%91%91%FD%15%15%15%FD%9A%A0%BD%FD%AC%BB%FD%FD%9F%AA%DE%FD%90%9A%C5%FD%A5%B3%F1%FD%9D%AB%E7%FD%7F%89%B7%FD%8F%97%BA%FD%E6%E6%E7%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FD%FD%FD%FD%AF%AF%AF%FDiii%FD%86%86%86%FD%B2%B2%B2%FDHHH%FD%A7%AC%C1%FD%C3%CD%FB%FD%C9%D2%FA%FD%A8%B0%D1%FD%AF%B6%D4%FD%A6%A9%B8%FDKKK%FD%FA%FA%FA%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%B5%B5%B5%FDzzz%FDeee%FD%1B%1B%1B%FDCCC%FD%88%88%88%FD%5C%5C%5C%FD%87%87%87%FDsss%FD%DB%DB%DB%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00(%00%00%00%10%00%00%00%20%00%00%00%01%00%20%00%00%00%00%00%00%04%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00SSS%FDaaa%FD%5E%5E%5E%FD%5E%5E%5E%FD000%FD%5D%5D%5D%FDIII%FDhhh%FDlYY%FDMCC%FD%A0%92%92%FDhVV%FDiii%FDAAA%FDiii%FDzzz%FDwww%FDhhh%FD%5E%5E%5E%FD%5E%5E%5E%FD555%FD%5C%5C%5C%FDKKK%FDbbb%FDs__%FDgcc%FD%5EZZ%FDbQQ%FD%84%84%84%FD%2F%2F%2F%FD%60%60%60%FD%D1%D1%D1%FD%7B%7B%7B%FDmmm%FD%5E%5E%5E%FD%5E%5E%5E%FDFFF%FDSSS%FDhhh%FDB%40%40%FDaQQ%FD%A3%A3%A3%FDXVV%FDWJJ%FD%94%94%94%FD---%FD%89%89%89%FD%FF%FF%FF%FD%89%89%89%FDooo%FD%5E%5E%5E%FD%5E%5E%5E%FD%5D%5D%5D%FDEEE%FD%83%83%83%FDMDD%FD%84%7F%7F%FD%FE%FE%FE%FDiii%FDB%3E%3E%FD%84%84%84%FD%5B%5B%5B%FD%FD%FD%FD%FD%FF%FF%FF%FD%BC%BC%BC%FDddd%FD%60%60%60%FD%60%60%60%FD%5C%5C%5C%FD___%FDiii%FDNJJ%FD%C3%C3%C3%FD%B9%B9%B9%FD%3B%3B%3B%FDTTT%FDIII%FD%DA%DA%DA%FD%FF%FF%FF%FD%FF%FF%FF%FD%FD%FD%FD%FD%7D%7D%7D%FDZZZ%FDfff%FDQQQ%FD%8B%8B%8B%FD%3F%3Fk%FD--P%FDCCk%FD11g%FD!!a%FD%8F%8F%8F%FD%EF%EF%EF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FB%FB%FB%FD%96%96%96%FDMMP%FD%96%96%A7%FDdl%A3%FD%A9%B3%E2%FDln%86%FD%96%96%AF%FD%F6%F6%F6%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%DD%DD%DD%FD%B1%B3%BA%FD%AD%BC%FF%FD%AD%BC%FF%FDy%81%A3%FD%ED%ED%ED%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%9E%A1%AF%FD%AC%BB%FE%FD~%87%B0%FDvy%88%FDttt%FD%D6%D6%D6%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%ED%ED%ED%FD%8D%97%C6%FD%8E%99%C6%FD%AC%B6%E3%FD%B0%BE%FF%FD%BD%C8%FC%FD%80%81%84%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%A4%A8%BB%FD%AC%BB%FD%FD%AB%BA%FC%FD%AD%BC%FF%FD%8B%97%CC%FDlu%9C%FD%82%89%A6%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FB%FB%FB%FD%8B%90%A5%FDkr%93%FD%A8%B6%F7%FD%9A%A7%E2%FDW%5Cq%FDX%5Ds%FD%5Dbz%FDW%5Bo%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%C1%C1%C1%FDqu%86%FD%82%82%85%FD%C9%D3%FF%FD%A3%AF%E4%FD%96%9D%BE%FD%A8%AB%B8%FD%89%8D%9E%FD%96%98%A1%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%AE%AE%AE%FD%8C%8C%8C%FD%7D~%82%FD%AD%B9%F1%FD%99%A0%BE%FD%BA%C6%FD%FD%A4%B2%F2%FDip%8F%FD%F4%F4%F4%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%B4%B4%B4%FD%B7%B7%B7%FDFFH%FD%9D%A7%D4%FDy%81%A6%FD%9B%A8%E3%FDnv%99%FD%B9%BA%BE%FD%F2%F2%F2%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FE%FE%FE%FD%C5%C5%C5%FD%9A%9A%9A%FD%5C%5Db%FD%96%9B%B0%FD%8F%92%A2%FD%90%90%94%FD%FD%FD%FD%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%FF%FF%FF%FD%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00</Image>
+ <Url type="text/html" method="GET" template="${rootURL}search/?q={searchTerms}" />
+ <Url type="application/x-suggestions+json" template="${rootURL}search/suggestOpenSearch?q={searchTerms}"/>
+</OpenSearchDescription>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/option.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/option.jelly
new file mode 100644
index 0000000..615651f
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/option.jelly
@@ -0,0 +1,36 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:d="jelly:define" xmlns:st="jelly:stapler">
+ <st:documentation>
+ &lt;option> tag for the &lt;select> element that takes true/false for selected.
+
+ <st:attribute name="value">
+ The value to be sent when the form is submitted.
+ If omitted, the body of the tag will be placed in the value attribute as well
+ (due to the browser incompatibility between IE and Firefox, value attribute
+ must be included).
+ </st:attribute>
+ <st:attribute name="selected" type="boolean">
+ If true, the option value appears as selected.
+ </st:attribute>
+ </st:documentation>
+ <!-- No escape/encode to avoid double-encoding if used in value attribute below -->
+ <j:set var="optionBody" encode="false"><d:invokeBody escapeText="false"/></j:set>
+ <option value="${attrs.value!=null?attrs.value:h.xmlUnescape(optionBody)}"
+ selected="${attrs.selected?'true':null}"><j:out value="${optionBody}"/></option>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/optionalBlock.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/optionalBlock.jelly
new file mode 100644
index 0000000..da3a722
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/optionalBlock.jelly
@@ -0,0 +1,88 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Nikita Levyankov, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Foldable block that can be expanded to show more controls by checking the checkbox.
+
+ <st:attribute name="name">
+ Name of the checkbox. Can be used by the server to determine
+ if the block is collapsed or expanded at the time of submission.
+
+ Note that when the block is collapsed, none of its child controls will send
+ the values to the server (unlike &lt;f:advanced>)
+ </st:attribute>
+ <st:attribute name="title">
+ Human readable text that follows the checkbox.
+ </st:attribute>
+ <st:attribute name="field">
+ Used for databinding. TBD. Either this or @name/@title combo is required.
+ </st:attribute>
+ <st:attribute name="checked">
+ initial checkbox status. true/false.
+ </st:attribute>
+ <st:attribute name="help">
+ If present, the (?) icon will be rendered on the right to show inline help.
+ See @help for &lt;f:entry>.
+ </st:attribute>
+ <st:attribute name="negative">
+ if present, the foldable section expands when the checkbox is unchecked.
+ </st:attribute>
+ <st:attribute name="inline">
+ if present, the foldable section will not be grouped into a separate JSON object upon submission
+ </st:attribute>
+ <st:attribute name="resetUrl">
+ If present, Redo icon will rendered and Reset will be available.
+ </st:attribute>
+ <st:attribute name="isPropertyOverridden">
+ if present and true - value is overridden
+ </st:attribute>
+ </st:documentation>
+ <j:if test="${attrs.help==null}">
+ <!-- infer the help page from the current descriptor and field if possible -->
+ <j:set target="${attrs}" property="help"
+ value="${descriptor.getHelpFile(attrs.field)}" />
+ </j:if>
+ <j:if test="${attrs.isPropertyOverridden==null}">
+ <j:set target="${attrs}" property="isPropertyOverridden" value="false"/>
+ </j:if>
+
+ <tr class="optional-block-start ${attrs.inline?'':'row-set-start'}" hasHelp="${attrs.help!=null}"><!-- this ID marks the beginning -->
+ <td colspan="3" class="${attrs.isPropertyOverridden? 'modified': 'original'}">
+ <j:if test="${attrs.isPropertyOverridden and !empty(attrs.resetUrl)}">
+ <div class="optional-reset">
+ <a href="#" class="reset-button" resetURL="${resetUrl}">
+ <img src="${imagesURL}/16x16/undo.png" alt="Reset ${title}" />
+ </a>
+ </div>
+ </j:if>
+ <f:checkbox name="${attrs.name}" onclick="javascript:updateOptionalBlock(this,true)"
+ negative="${attrs.negative}" checked="${attrs.checked}" field="${attrs.field}" title="${title}" />
+ </td>
+ <j:if test="${attrs.help!=null}">
+ <td>
+ <a href="#" class="help-button" helpURL="${rootURL}${attrs.help}"><img src="${imagesURL}/16x16/help.png" alt="Help for feature: ${title}" /></a>
+ </td>
+ </j:if>
+ </tr>
+ <j:if test="${attrs.help!=null}">
+ <f:helpArea />
+ </j:if>
+ <d:invokeBody />
+ <!-- end marker -->
+ <tr class="${attrs.inline?'':'row-set-end'} optional-block-end" />
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/optionalProperty.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/optionalProperty.jelly
new file mode 100644
index 0000000..e6a6b8a
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/optionalProperty.jelly
@@ -0,0 +1,39 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2010, CollabNet
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Renders inline an optional single-value nested data-bound property of the current instance,
+ by using a &lt;f:optionalBlock>
+
+ This is useful when your object composes another data-bound object, and when that's optional,
+ where the absence of the value is signified as null (in which case the optionalBlock will be drawn unchecked),
+ and the presence of the value.
+ <st:attribute name="field" use="required" />
+ <st:attribute name="title" use="required" />
+ </st:documentation>
+ <!--
+ Without @checked, optionalBlock will try to coarse an obejct to a boolean, which fails,
+ so override @checked manually.
+ -->
+ <f:optionalBlock field="${field}" title="${title}" checked="${instance[field]!=null}">
+ <j:set var="descriptor" value="${app.getDescriptorOrDie(descriptor.getPropertyType(instance,field).clazz)}" />
+ <j:set var="instance" value="${instance[field]}"/>
+ <st:include from="${descriptor}" page="${descriptor.configPage}" />
+ </f:optionalBlock>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/outline.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/outline.jelly
new file mode 100644
index 0000000..f4d8b9a
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/outline.jelly
@@ -0,0 +1,30 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project">
+ <l:ajax>
+ <table class='pane' id='console-outline'>
+ <tr>
+ <td class='pane-header'>${%Executed Ant Targets}</td>
+ </tr>
+ <tr>
+ <td id='console-outline-body' />
+ </tr>
+ </table>
+ </l:ajax>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/pane.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/pane.jelly
new file mode 100644
index 0000000..d2a0cd1
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/pane.jelly
@@ -0,0 +1,44 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:d="jelly:define" xmlns:st="jelly:stapler">
+ <st:documentation>
+ Used in the &lt;l:side-panel> to draw a box with a title.
+
+ The box is drawn as a table, and the body of this tag
+ is expected to draw a series of &lt;TR>s to fill in the contents
+ of the box.
+
+ <st:attribute name="title" use="required">
+ Title of the box. Can include HTML.
+ </st:attribute>
+ <st:attribute name="width" use="required">
+ Specify the number of columns in the table
+ (so that the title can stretch to the entire table width.
+ </st:attribute>
+ <st:attribute name="id">
+ @id of the table, if specified.
+ </st:attribute>
+ </st:documentation>
+ <table class="pane" id="${attrs.id}">
+ <tr><td class="pane-header" colspan="${width}">
+ <j:out value="${title}"/>
+ </td></tr>
+ <d:invokeBody />
+ </table>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/password.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/password.jelly
new file mode 100644
index 0000000..cd49b70
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/password.jelly
@@ -0,0 +1,55 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:d="jelly:define" xmlns:st="jelly:stapler" xmlns:f="/lib/form">
+ <st:documentation>
+ Glorified &lt;input type="password">
+
+ <st:attribute name="field">
+ Used for databinding. TBD.
+ </st:attribute>
+ <st:attribute name="name">
+ This becomes @name of the &lt;input> tag.
+ If @field is specified, this value is inferred from it.
+ </st:attribute>
+ <st:attribute name="value">
+ The initial value of the field. This becomes the @value of the &lt;input> tag.
+ If @field is specified, the current property from the "instance" object
+ will be set as the initial value automatically,
+ which is the recommended approach.
+ </st:attribute>
+ <st:attribute name="clazz">
+ Additional CSS class(es) to add (such as client-side validation clazz="required",
+ "number" or "positive-number"; these may be combined, as clazz="required number").
+ </st:attribute>
+ <st:attribute name="checkUrl">
+ If specified, the value entered in this input field will be checked (via AJAX)
+ against this URL, and errors will be rendered under the text field.
+
+ If @field is specified, this will be inferred automatically,
+ which is the recommended approach.
+ </st:attribute>
+ </st:documentation>
+ <f:prepareDatabinding />
+ <m:input xmlns:m="jelly:hudson.util.jelly.MorphTagLibrary"
+ class="setting-input ${attrs.checkUrl!=null?'validated ':''}${attrs.clazz}"
+ name ="${attrs.name ?: '_.'+attrs.field}"
+ value="${h.getPasswordValue(attrs.value ?: instance[attrs.field])}"
+ type="password"
+ ATTRIBUTES="${attrs}" EXCEPT="field clazz" />
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/permalinks.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/permalinks.jelly
new file mode 100644
index 0000000..8f481ee
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/permalinks.jelly
@@ -0,0 +1,28 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!-- display permalinks of the page -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project">
+ <h2>${%Permalinks}</h2>
+ <ul>
+ <j:set var="job" value="${it}" />
+ <j:forEach var="p" items="${it.permalinks}">
+ <st:include page="link.jelly" it="${p}"/>
+ </j:forEach>
+ </ul>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/prepareDatabinding.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/prepareDatabinding.jelly
new file mode 100644
index 0000000..2dcbce2
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/prepareDatabinding.jelly
@@ -0,0 +1,31 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define">
+ <st:documentation>
+ Modifies the 'attrs.field' of the parent to inherit @field from the enclosing &lt;f:entry>
+ if available. Also computes the @checkUrl attribute.
+ </st:documentation>
+ <j:set var="pattrs" value="${parentScope.attrs}" />
+ <j:if test="${pattrs.field==null}">
+ <!-- this looks up the ancestor <entry> set by entry.jelly -->
+ <j:set target="${pattrs}" property="field" value="${entry.field}" />
+ </j:if>
+ <j:set target="${pattrs}" property="checkUrl"
+ value="${h.getCheckUrl(pattrs.checkUrl,descriptor,pattrs.field)}" />
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/progressBar.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/progressBar.jelly
new file mode 100644
index 0000000..16f7e75
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/progressBar.jelly
@@ -0,0 +1,43 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Progress bar. @pos (0-100) specifies the current position
+
+ Attributes:
+ pos : 0-100 to indicates the current progress. -1 if the progress is unknown
+ href : if set, the progress bar becomes a hyperlink
+ red : if set to non-null, the progress bar will be drawn in red, to indicate that the processing is likely stuck.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <table class="progress-bar ${attrs.red?'red':null}" id="${attrs.id}" tooltip="${attrs.tooltip}" href="${attrs.href}" style="${attrs.href!=null ? 'cursor:pointer' : null}">
+ <j:choose>
+ <j:when test="${pos lt 0}">
+ <!-- style sheet will fill in the progress bar image -->
+ <tbody><tr class="unknown"><td/></tr></tbody>
+ </j:when>
+ <j:otherwise>
+ <tbody><tr>
+ <td class="progress-bar-done" style="width:${pos}%;"/>
+ <td class="progress-bar-left" style="width:${100-pos}%"/>
+ </tr>
+ </tbody>
+ </j:otherwise>
+ </j:choose>
+ </table>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/progressiveText.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/progressiveText.jelly
new file mode 100644
index 0000000..3c93f2c
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/progressiveText.jelly
@@ -0,0 +1,87 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Yahoo! Inc.
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Use AJAX to load text data progressively.
+ This is used to achieve the effect of "tail -f"
+ without relying on full page reload.
+
+ <%@attribute name="href" required="true" description="URL that returns text data" %>
+ <%@attribute name="idref" required="true" description="ID of the HTML element in which the result is displayed" %>
+ <%@attribute name="spinner" required="false" description="ID of the HTML element in which the spinner is displayed" %>
+ <%@attribute name="startOffset" required="false" description="Skip this many bytes rather than showing from start of data" %>
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <!--
+ script code
+ -->
+ <script>
+ var scroller = new AutoScroller(document.body);
+ <j:if test="${requestScope.progressiveTextScript==null}">
+ <j:set target="${requestScope}" property="progressiveTextScript" value="initialized" />
+ <!--
+ fetches the latest update from the server
+
+ @param e
+ DOM node that gets the text appended to
+ @param href
+ Where to retrieve additional text from
+ -->
+ function fetchNext(e,href) {
+ var headers = {};
+ if (e.consoleAnnotator!=undefined)
+ headers["X-ConsoleAnnotator"] = e.consoleAnnotator;
+
+ new Ajax.Request(href,{
+ method: "post",
+ parameters: {"start":e.fetchedBytes},
+ requestHeaders: headers,
+ onComplete: function(rsp,_) {
+ <!-- append text and do autoscroll if applicable-->
+ var stickToBottom = scroller.isSticking();
+ var text = rsp.responseText;
+ if(text!="") {
+ var p = document.createElement("DIV");
+ e.appendChild(p); // Needs to be first for IE
+ // Use "outerHTML" for IE; workaround for:
+ // http://www.quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html
+ if (p.outerHTML) {
+ p.outerHTML = '<pre>'+text+'</pre>';
+ p = e.lastChild;
+ }
+ else p.innerHTML = text;
+ Behaviour.applySubtree(p);
+ if(stickToBottom) scroller.scrollToBottom();
+ }
+
+ e.fetchedBytes = rsp.getResponseHeader("X-Text-Size");
+ e.consoleAnnotator = rsp.getResponseHeader("X-ConsoleAnnotator");
+ if(rsp.getResponseHeader("X-More-Data")=="true")
+ setTimeout(function(){fetchNext(e,href);},1000);
+ <j:if test="${spinner!=null}">
+ else
+ $$("${spinner}").style.display = "none";
+ </j:if>
+ }
+ });
+ }
+ </j:if>
+ $$("${idref}").fetchedBytes = ${empty(startOffset)?0:startOffset};
+ fetchNext($$("${idref}"),"${href}");
+ </script>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/project-changes.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/project-changes.jelly
new file mode 100644
index 0000000..6e04180
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/project-changes.jelly
@@ -0,0 +1,70 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe, Tom Huybrechts, id:cactusman
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ This view is used to render the project change list like /job/<jobname>/changes
+
+ While this default implementation can work with any SCM,
+ subclass may provide diffent implementation to present implementation-specific
+ information.
+
+ The 'builds' variable contains the collection of AbstractBuild objects
+ for which the change should be displayed.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <j:choose>
+ <j:when test="${empty(builds)}">
+ ${%No builds.}
+ </j:when>
+ <j:otherwise>
+ <j:set var="hadChanges" value="${false}"/>
+ <j:forEach var="b" items="${builds}">
+ <j:if test="${b.changeSet.iterator().hasNext()}">
+ <j:set var="hadChanges" value="${true}"/>
+ <h2><a href="${b.number}/changes">${b.displayName}
+ (<i:formatDate value="${b.timestamp.time}" type="both" dateStyle="medium" timeStyle="medium"/>)</a></h2>
+
+ <ol>
+ <j:forEach var="c" items="${b.changeSet.iterator()}" varStatus="loop">
+ <li value="${c.revision}">
+ <j:out value="${c.msgAnnotated}"/>
+
+ &#8212;
+
+ <a href="${rootURL}/${c.author.url}/">${c.author}</a> /
+
+ <j:set var="cslink" value="${browser.getChangeSetLink(c)}"/>
+ <j:choose>
+ <j:when test="${cslink!=null}">
+ <a href="${cslink}">${browser.descriptor.displayName}</a>
+ </j:when>
+ <j:otherwise>
+ <a href="${b.number}/changes#detail${loop.index}">${%detail}</a>
+ </j:otherwise>
+ </j:choose>
+ </li>
+ </j:forEach>
+ </ol>
+ </j:if>
+ </j:forEach>
+ <j:if test="${!hadChanges}">
+ ${%No changes in any of the builds.}
+ </j:if>
+ </j:otherwise>
+ </j:choose>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/projectActionFloatingBox.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/projectActionFloatingBox.jelly
new file mode 100644
index 0000000..b97fde4
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/projectActionFloatingBox.jelly
@@ -0,0 +1,34 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Used in the index page to show floating boxes contributed from project actions.
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <div style="float:right">
+ <j:forEach var="a" items="${it.actions}">
+ <!--
+ For historical reason, we failed to expose the action as "it", so
+ this exposes it as "action", without breaking the compatibility with plugins
+ that may depend on the 'a' variable.
+ -->
+ <j:set var="action" value="${a}" />
+ <st:include page="floatingBox.jelly" from="${a}" optional="true" />
+ </j:forEach>
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/projectRelationship-help.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/projectRelationship-help.jelly
new file mode 100644
index 0000000..6ebba2b
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/projectRelationship-help.jelly
@@ -0,0 +1,42 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, id:cactusman, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <l:layout>
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <h1>${%Title}</h1>
+ <p>
+ ${%body}
+ </p>
+ <p>
+ ${%For this feature to work, the following conditions need to be met:}
+ </p>
+ <ol>
+ <li>${%The upstream project records the fingerprints of its build artifacts}</li>
+ <li>${%The downstream project records the fingerprints of the upstream files it uses}</li>
+ </ol>
+ <p>
+ ${%This allows Hudson to correlate two projects.}
+ </p>
+ <p>
+ ${%Upstream note}
+ </p>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/projectRelationship.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/projectRelationship.jelly
new file mode 100644
index 0000000..8483363
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/projectRelationship.jelly
@@ -0,0 +1,88 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, id:cactusman
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Displays two projects side by side and show their relationship
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <l:layout norefresh="true">
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <h1><img src="${imagesURL}/48x48/search.png" alt=""/>${%Project Relationship}</h1>
+ <form action="projectRelationship" method="get">
+ <table width="100%">
+ <tr>
+ <j:set var="names" value="${app.jobNames}" />
+ <td style="text-align:right;">
+ ${%upstream project}:
+ <f:editableComboBox id="lhs" name="lhs" value="${request.getParameter('lhs')}" items="${names}" />
+ </td>
+ <td style="width:32px; text-align:center;"><img src="${imagesURL}/24x24/next.png" alt="->"/></td>
+ <td>
+ ${%downstream project}:
+ <f:editableComboBox id="rhs" name="rhs" value="${request.getParameter('rhs')}" items="${names}" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3" style="text-align:right">
+ <f:submit value="${%Compare}" />
+ <a href="projectRelationship-help"><img src="${imagesURL}/16x16/help.png" alt="[help]"/></a>
+ </td>
+ </tr>
+
+ <j:if test="${!empty(request.getParameter('lhs')) and !empty(request.getParameter('rhs'))}">
+ <j:set var="jl" value="${app.getItemByFullName(request.getParameter('lhs'))}" />
+ <j:set var="jr" value="${app.getItemByFullName(request.getParameter('rhs'))}" />
+
+ <j:choose>
+ <j:when test="${jl==null}">
+ <tr><td colspan="3" class="error">
+ No such project '${request.getParameter('lhs')}'
+ </td></tr>
+ </j:when>
+ <j:when test="${jr==null}">
+ <tr><td colspan="3" class="error">
+ No such project '${request.getParameter('rhs')}'
+ </td></tr>
+ </j:when>
+ <j:otherwise>
+ <j:set var="relation" value="${jl.getRelationship(jr)}"/>
+ <j:if test="${empty(relation)}">
+ <tr><td colspan="3" class="error">
+ ${%There are no fingerprint records that connect these two projects.}
+ </td></tr>
+ </j:if>
+ <j:forEach var="e" items="${relation}">
+ <tr>
+ <td style="text-align:right">
+ <t:buildLink job="${jl}" number="${e.key}"/>
+ </td>
+ <td><st:nbsp/></td>
+ <td>
+ <t:buildRangeLink job="${jr}" range="${e.value}"/>
+ </td>
+ </tr>
+ </j:forEach>
+ </j:otherwise>
+ </j:choose>
+ </j:if>
+ </table>
+ </form>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/projectView.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/projectView.jelly
new file mode 100644
index 0000000..bca5e4e
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/projectView.jelly
@@ -0,0 +1,77 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Stephen Connolly, id:cactusman, Martin Eigenbrodt
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout"
+ xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Renders a list of jobs and their key information.
+
+ <st:attribute name="jobs" use="required" trim="Collection">
+ Items to disable.
+ </st:attribute>
+ <st:attribute name="jobBaseUrl" type="String">
+ The base URL of all job links. Normally ${rootURL}/
+ </st:attribute>
+ <st:attribute name="showViewTabs" use="optional" type="boolean">
+ If the caller rendered a view tabes, set this attribute so that CSS is adjusted accordingly.
+ </st:attribute>
+ <st:attribute name="views" type="Collection&lt;View>">
+ If non-null, render nested views.
+ </st:attribute>
+ <st:attribute name="indenter" type="hudson.Indenter">
+ Optional Indenter instance used to indent items.
+ </st:attribute>
+ <st:attribute name="columnExtensions" type="Collection&lt;hudson.views.ListViewColumn>">
+ List view columns to render. If omitted, the default ones from ListView.getDefaultColumns() are used.
+ </st:attribute>
+ </st:documentation>
+
+ <t:setIconSize/>
+ <div class="dashboard">
+
+ <j:if test="${columnExtensions==null}">
+ <j:invokeStatic var="columnExtensions" className="hudson.model.ListView" method="getDefaultColumns"/>
+ </j:if>
+
+ <j:if test="${!empty(jobs) or !empty(attrs.views)}">
+ <!-- the caller can inject a tab bar here -->
+ <d:invokeBody/>
+ <!-- project list -->
+ <table id="projectstatus" class="sortable pane bigtable"
+ style="${showViewTabs!=null?'margin-top:0px; border-top: none;':null}">
+ <tr style="border-top: 0px;">
+ <j:forEach var="col" items="${columnExtensions}">
+ <st:include page="columnHeader.jelly" it="${col}" />
+ </j:forEach>
+ <th>
+ <st:nbsp/>
+ </th>
+ </tr>
+
+ <j:forEach var="v" items="${attrs.views}">
+ <t:projectViewNested />
+ </j:forEach>
+
+ <j:forEach var="job" items="${jobs}">
+ <t:projectViewRow />
+ </j:forEach>
+ </table>
+ <t:iconSize><t:rssBar/></t:iconSize>
+ </j:if>
+ </div>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/projectViewNested.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/projectViewNested.jelly
new file mode 100644
index 0000000..a77d8ac
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/projectViewNested.jelly
@@ -0,0 +1,49 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ Renders the nest view in <projectView />
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout"
+ xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <tr>
+ <td colspan="2">
+ <div style="${indenter.getRelativeShift(job)}">
+ <j:choose>
+ <j:when test="${request.getView(v,'ajaxRows.jelly')==null}">
+ <img src="${imagesURL}/none.gif" state="plus" width="14" height="14" alt="" />
+ </j:when>
+ <j:otherwise>
+ <!-- if nested view supports ajaxRows -->
+ <a href="#">
+ <img src="${imagesURL}/tree/plus.png" state="plus" width="14" height="14" alt="" class="fold-control treeview-fold-control"
+ url="${rootURL}/${v.url}/ajaxRows?depth=${depth!=null?depth+1:1}"/>
+ <st:adjunct includes="lib.hudson.projectViewNested" />
+ </a>
+ </j:otherwise>
+ </j:choose>
+ <img src="${imagesURL}/${iconSize}/folder.png" style="margin-left:4px" alt="" />
+ </div>
+ </td>
+ <td colspan="5" style="${indenter.getCss(job)}">
+ <a href="${rootURL}/${v.url}">
+ ${v.viewName}
+ </a>
+ </td>
+ </tr>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/projectViewRow.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/projectViewRow.jelly
new file mode 100644
index 0000000..fd4563c
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/projectViewRow.jelly
@@ -0,0 +1,37 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Martin Eigenbrodt
+#
+#
+#************************************************************************** -->
+
+
+<!--
+
+ Attributes:
+ @job : job to draw
+ @indenter
+-->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout"
+ xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <j:set var="lsBuild" value="${job.lastSuccessfulBuild}"/>
+ <j:set var="lfBuild" value="${job.lastFailedBuild}"/>
+ <tr class="${job.disabled?'disabledJob':null}">
+ <j:forEach var="col" items="${columnExtensions}">
+ <st:include page="column.jelly" it="${col}" />
+ </j:forEach>
+ <td>
+ <st:nbsp/>
+ </td>
+ </tr>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/property.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/property.jelly
new file mode 100644
index 0000000..0e743b9
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/property.jelly
@@ -0,0 +1,35 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2010, CollabNet
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+#
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Renders inline a single-value nested data-bound property of the current instance.
+ This is useful when your object composes another data-bound object as a nested object,
+ yet your UI would still like to render it
+
+ <st:attribute name="field" use="required" />
+ <st:attribute name="propertyDescriptor">
+ If specified, bypass the item descriptor inference and use this instead.
+ </st:attribute>
+ </st:documentation>
+ <f:rowSet name="${field}">
+ <j:set var="descriptor" value="${attrs.propertyDescriptor ?: app.getDescriptorOrDie(descriptor.getPropertyType(instance,field).clazz)}" />
+ <j:set var="instance" value="${instance[field]}"/>
+ <st:include from="${descriptor}" page="${descriptor.configPage}" />
+ </f:rowSet>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/propertyTable.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/propertyTable.jelly
new file mode 100644
index 0000000..8d7442b
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/propertyTable.jelly
@@ -0,0 +1,44 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Dispaly sortable table of properties.
+
+ <st:attribute name="items" use="required">
+ A Map object that gets rendered as a table.
+ </st:attribute>
+ </st:documentation>
+ <table class="pane sortable">
+ <tr>
+ <th class="pane-header" initialSortDir="down">${%Name}</th>
+ <th class="pane-header">${%Value}</th>
+ </tr>
+ <j:forEach var="e" items="${items}">
+ <tr>
+ <td class="pane"><st:out value="${e.key}"/></td>
+ <td class="pane">
+ <j:invokeStatic var="escapedValue" className="hudson.Util" method="escapeString">
+ <j:arg value="${e.value}" />
+ </j:invokeStatic>
+ <j:out value="${escapedValue}"/>
+ </td>
+ </tr>
+ </j:forEach>
+ </table>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/queue.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/queue.jelly
new file mode 100644
index 0000000..5a85b18
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/queue.jelly
@@ -0,0 +1,98 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Tom Huybrechts, Yahoo! Inc.
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Displays the build queue as &lt;l:pane>
+
+ <st:attribute name="items" use="required">
+ Queue items to be displayed. Normally you should specify ${app.queue.items},
+ but for example you can specify a sublist after some filtering to narrow down
+ the list.
+ </st:attribute>
+ </st:documentation>
+ <t:setIconSize/>
+ <l:pane title="${%Build Queue}" width="2" id="buildQueue">
+ <j:if test="${app.quietingDown}">
+ <tr>
+ <td class="pane" colspan="2" style="white-space: normal;">
+ ${%Hudson is going to shut down. No further builds will be performed.}
+ <j:if test="${h.hasPermission(app.ADMINISTER)}">
+ <a href="${rootURL}/cancelQuietDown">(${%cancel})</a>
+ </j:if>
+ </td>
+ </tr>
+ </j:if>
+ <j:choose>
+ <j:when test="${empty(items)}">
+ <j:if test="${! app.quietingDown}">
+ <tr>
+ <td class="pane" colspan="2">
+ ${%No builds in the queue.}
+ </td>
+ </tr>
+ </j:if>
+ </j:when>
+ <j:otherwise>
+ <j:forEach var="item" items="${items}">
+ <tr>
+ <td class="pane" width="100%" tooltip="${item.why}${h.escape(item.params)}" style="white-space: normal;">
+ <j:set var="stuck" value="${item.isStuck()}"/>
+ <j:choose>
+ <j:when test="${h.hasPermission(item.task,item.task.READ)}">
+ <a href="${rootURL}/${item.task.url}">
+ ${item.task.fullDisplayName}
+ </a>
+ <j:if test="${stuck}">
+ &#160;
+ <a href="http://wiki.hudson-ci.org/display/HUDSON/Executor+Starvation">
+ <img src="${imagesURL}/16x16/hourglass.png" />
+ </a>
+ </j:if>
+ </j:when>
+ <j:otherwise>
+ <span>${%Unknown Task}</span>
+ </j:otherwise>
+ </j:choose>
+ </td>
+ <td class="pane" width="16" align="center" valign="middle">
+ <j:if test="${item.hasCancelPermission()}">
+ <a href="${rootURL}/queue/item/${item.id}/cancelQueue"><img src="${imagesURL}/16x16/stop.png" alt="cancel this build" /></a>
+ </j:if>
+ </td>
+ </tr>
+ </j:forEach>
+ <tr>
+ <td class="pane" style="text-align: right" colspan="2">
+ <j:if test="${h.hasPermission(app.ADMINISTER)}">
+ <a href="${rootURL}/queue/clearQueue">
+ (${%cancel all})
+ </a>
+ </j:if>
+ </td>
+ </tr>
+ </j:otherwise>
+ </j:choose>
+ </l:pane>
+ <!-- schedule updates only for the full page reload -->
+ <j:if test="${ajax==null and !h.isAutoRefresh(request) and h.hasPermission(app.READ)}">
+ <script defer="defer">
+ refreshPart('buildQueue',"${h.hasView(it,'ajaxBuildQueue')?'.':rootURL}/ajaxBuildQueue");
+ </script>
+ </j:if>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/radio.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/radio.jelly
new file mode 100644
index 0000000..5aaeef2
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/radio.jelly
@@ -0,0 +1,25 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi
+#
+#
+#************************************************************************** -->
+
+
+<!--
+ <input type="radio"> tag that takes true/false for @checked.
+
+ Note that safari doesn't support onchange.
+-->
+<?jelly escape-by-default='true'?>
+<input type="radio" name="${attrs.name}" onclick="${attrs.onclick}" id="${attrs.id}" value="${attrs.value}"
+ checked="${attrs.checked?'true':null}"/>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/radioBlock.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/radioBlock.jelly
new file mode 100644
index 0000000..13703c1
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/radioBlock.jelly
@@ -0,0 +1,72 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2011 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Anton Kozak
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation>
+ Radio button with a label that hides additional controls.
+ When checked, those additional controls are displayed. This is useful
+ for presenting mutually exclusive options, where each option comes
+ with a sub-form that provides additional configuration.
+
+ <st:attribute name="name" use="required">
+ Name of the radio button group. Radio buttons that are mutually exclusive need
+ to have the same name.
+ </st:attribute>
+ <st:attribute name="value" use="required">
+ @value of the &lt;input> element.
+ </st:attribute>
+ <st:attribute name="title" use="required">
+ Human readable label text to be rendered next to the radio button.
+ </st:attribute>
+ <st:attribute name="checked" use="required" type="boolean">
+ Should this control be initially checked or not?
+ </st:attribute>
+ <st:attribute name="help">
+ If specified, the (?) help icon will be rendered on the right,
+ for in place help text. See &lt;f:entry> for the details.
+ </st:attribute>
+ <st:attribute name="isPropertyOverridden">
+ if present and true - value is overridden
+ </st:attribute>
+ </st:documentation>
+
+ <j:if test="${attrs.isPropertyOverridden==null}">
+ <j:set target="${attrs}" property="isPropertyOverridden" value="false"/>
+ </j:if>
+ <tr class="radio-block-start" hasHelp="${attrs.help!=null}"><!-- this ID marks the beginning -->
+ <td colspan="3" class="${attrs.isPropertyOverridden? 'modified': 'original'}">
+ <input type="radio" name="${name}" value="${value}"
+ class="radio-block-control" checked="${checked?'true':null}"/>
+ <st:nbsp/>
+ <label class="attach-previous">${title}</label>
+ </td>
+ <j:if test="${attrs.help!=null}">
+ <td>
+ <a href="#" class="help-button" helpURL="${rootURL}${help}">
+ <img src="${imagesURL}/16x16/help.png" alt="Help for feature: ${title}"/>
+ </a>
+ </td>
+ </j:if>
+ </tr>
+ <j:if test="${attrs.help!=null}">
+ <f:helpArea/>
+ </j:if>
+ <d:invokeBody/>
+ <!-- end marker -->
+ <tr class="radio-block-end" style="display:none"/>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/readOnlyTextbox.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/readOnlyTextbox.jelly
new file mode 100644
index 0000000..4b0d337
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/readOnlyTextbox.jelly
@@ -0,0 +1,67 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Yahoo!, Inc.
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:f="/lib/form">
+ <st:documentation>
+ Generates an input field <tt>&lt;input type="text" ... /></tt> to be
+ used inside &lt;f:entry/>
+
+ <st:attribute name="field">
+ Used for databinding. TBD.
+ </st:attribute>
+ <st:attribute name="name">
+ This becomes @name of the &lt;input> tag.
+ If @field is specified, this value is inferred from it.
+ </st:attribute>
+ <st:attribute name="value">
+ The initial value of the field. This becomes the @value of the &lt;input> tag.
+ If @field is specified, the current property from the "instance" object
+ will be set as the initial value automatically,
+ which is the recommended approach.
+ </st:attribute>
+ <st:attribute name="default">
+ The default value of the text box, in case both @value is and 'instance[field]' is null.
+ </st:attribute>
+ <!-- Tomcat doesn't like us using the attribute called 'class' -->
+ <st:attribute name="clazz">
+ Additional CSS class(es) to add (such as client-side validation clazz="required",
+ "number" or "positive-number"; these may be combined, as clazz="required number").
+ </st:attribute>
+ <st:attribute name="checkMessage">
+ Override the default error message when client-side validation fails,
+ as with clazz="required", etc.
+ </st:attribute>
+ <st:attribute name="checkUrl">
+ If specified, the value entered in this input field will be checked (via AJAX)
+ against this URL, and errors will be rendered under the text field.
+
+ If @field is specified, this will be inferred automatically,
+ which is the recommended approach.
+ </st:attribute>
+ </st:documentation>
+ <f:prepareDatabinding />
+ <input class="setting-input ${attrs.checkUrl!=null?'validated':''} ${attrs.clazz}"
+ name="${attrs.name ?: '_.'+attrs.field}"
+ value="${attrs.value ?: instance[attrs.field] ?: attrs.default}"
+ id="${attrs.id}"
+ type="text"
+ readonly="readonly"
+ checkUrl="${attrs.checkUrl}" checkMethod="${attrs.checkMethod}"
+ checkMessage="${attrs.checkMessage}"
+ onchange="${attrs.onchange}" onkeyup="${attrs.onkeyup}"/>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/rename.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/rename.jelly
new file mode 100644
index 0000000..6cf9564
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/rename.jelly
@@ -0,0 +1,50 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2009 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Seiji Sogabe
+#
+#
+#************************************************************************** -->
+
+
+<!-- Rename project -->
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
+ <l:layout>
+ <st:include page="sidepanel.jelly" />
+ <l:main-panel>
+ <j:set var="newName" value="${request.getParameter('newName')}" />
+ <j:choose>
+ <j:when test="${it.isBuilding()}">
+ ${%noRenameWhileBuilding}
+ <j:if test="${request.referer.endsWith('/configure')}">
+ <br/> ${%configWasSaved}
+ </j:if>
+ </j:when>
+ <j:when test="${app.getItem(newName)!=null and !it.name.equalsIgnoreCase(newName)}">
+ ${%newNameInUse(newName)}
+ <j:if test="${request.referer.endsWith('/configure')}">
+ <br/> ${%configWasSaved}
+ </j:if>
+ </j:when>
+ <j:otherwise>
+ <form method="post" action="doRename">
+ ${%description(it.name, newName)}
+ <input type="hidden" name="newName" value="${newName}" />
+ <f:submit value="${%Yes}" />
+ <input type="button" value="${%No}"
+ onclick="javascript:history.back()" class="yui-button" />
+ </form>
+ </j:otherwise>
+ </j:choose>
+ </l:main-panel>
+ </l:layout>
+</j:jelly>
diff --git a/xpath-service/src/test/resources/org/hudsonci/xpath/repeatable.jelly b/xpath-service/src/test/resources/org/hudsonci/xpath/repeatable.jelly
new file mode 100644
index 0000000..587ed5c
--- /dev/null
+++ b/xpath-service/src/test/resources/org/hudsonci/xpath/repeatable.jelly
@@ -0,0 +1,148 @@
+<!-- **************************************************************************
+#
+# Copyright (c) 2004-2010 Oracle Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#
+# Kohsuke Kawaguchi, Alan Harder
+#
+#
+#************************************************************************** -->
+
+
+<?jelly escape-by-default='true'?>
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <st:documentation> <![CDATA[]
+ Repeatable blocks used to present UI where the user can configure multiple entries
+ of the same kind (see the Java installations configuration in the system config.)
+
+ This tag works like <j:forEach> and repeatedly evaluate the body so that
+ initially all the items get their own copy. This tag also evaluate the body
+ once more with var=null to create a 'master copy', which is the template entry
+ used when a new copy is inserted.
+
+ h1. HTML structure
+ this tag mainly produces the nested DIVs with CSS classes as follows:
+
+ {noformat}
+ <div class="repeated-container"> // container for the whole thing
+ <div class="repeated-chunk">
+ ... copy 1 ...
+ <div class="repeated-chunk">
+ ... copy 2 ...
+ ...
+ {noformat}
+
+ The 'repeated-chunk' DIVs will also have additional CSS classes that represent
+ their positions among siblings:
+
+ first : first chunk among the siblings
+ last : last chunk among the siblings