aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHirotaka Matsumoto2013-04-17 07:43:32 (EDT)
committerHirotaka Matsumoto2013-04-17 07:43:32 (EDT)
commit452e8780caa98abd1cdc21aeb00ca3e8461b7d13 (patch)
treeb8000a56bfce54710ea19e683a9cc263a928c6f9
parentf723c0764f0750d9d36f4b0c801149bfa4f7b7ef (diff)
downloadorg.eclipse.lyo.docs-452e8780caa98abd1cdc21aeb00ca3e8461b7d13.zip
org.eclipse.lyo.docs-452e8780caa98abd1cdc21aeb00ca3e8461b7d13.tar.gz
org.eclipse.lyo.docs-452e8780caa98abd1cdc21aeb00ca3e8461b7d13.tar.bz2
Bug 403983 - Initial contribution for Lyo Tracked Resource Set Providerrefs/changes/68/11968/1
for Bugzilla Change-Id: I14f0027db6548ba5e572da998be8281a4fc49dc8 Signed-off-by: Hirotaka Matsumoto <jljlmatu@jp.ibm.com>
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/.classpath11
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/.gitignore7
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/.project42
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/.jsdtscope12
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.jdt.core.prefs9
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.m2e.core.prefs5
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.common.component10
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.common.project.facet.core.xml7
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.jsdt.ui.superType.container1
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.jsdt.ui.superType.name1
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/TRS-SDK.pdfbin0 -> 1075007 bytes
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/about.html33
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/license/edl-v10.html60
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/license/epl-v10.html259
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/license/notice.html109
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/pom.xml132
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/BugzillaManager.java1053
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/Constants.java61
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/Credentials.java42
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/exception/BugzillaOAuthException.java29
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/exception/RestException.java59
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/exception/UnauthorizedException.java38
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/jbugzx/rpc/GetAccessibleProducts.java61
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/jbugzx/rpc/GetLegalValues.java64
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/BugzillaChangeRequest.java285
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/ChangeRequest.java890
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/Person.java76
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/Severity.java29
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/Type.java54
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/package-info.java38
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/BugzillaApplication.java110
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/BugzillaChangeRequestService.java960
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/RootServicesService.java54
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/ServiceProviderCatalogService.java175
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/ServiceProviderService.java166
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/TrackedResourceSetService.java139
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/AbstractAdapterCredentialsFilter.java507
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/BugzillaAdapterCredentialsFilter.java134
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/BugzillaAdapterCredentialsFilterMT.java151
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/BugzillaServiceProviderFactory.java92
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/CredentialsFilter.java360
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/ServiceProviderCatalogSingleton.java293
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/BugSearch2.java47
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/ChangeBugzillaHistories.java418
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/GetComments.java108
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/GetHistory.java104
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/GetProduct.java98
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/HistoryData.java93
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/BugzillaHttpClient.java150
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/HttpUtils.java112
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/StringUtils.java73
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/XmlUtils.java61
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/resources/bugz.properties28
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/resources/jetty.xml25
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/META-INF/MANIFEST.MF3
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/WEB-INF/lib/.gitignore0
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/WEB-INF/web.xml81
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/bugzilla.js143
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_collection_html.jsp91
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_creator.jsp141
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_filtered_json.jsp33
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_preview_large.jsp66
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_preview_small.jsp102
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_selector.jsp74
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/rootservices_rdfxml.jsp52
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/serviceprovider_html.jsp146
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/serviceprovidercatalog_html.jsp109
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/images/resources/bugzilla.gifbin0 -> 30743 bytes
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/images/resources/oslc.pngbin0 -> 805 bytes
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/images/resources/oslcLg.pngbin0 -> 7149 bytes
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/index.jsp5
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/test/java/.gitignore0
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/test/launches/Launch TRS Reference App for Bugzilla.launch15
-rw-r--r--org.eclipse.lyo.oslc4j.bugzilla.trs/src/test/resources/.gitignore0
74 files changed, 8996 insertions, 0 deletions
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/.classpath b/org.eclipse.lyo.oslc4j.bugzilla.trs/.classpath
new file mode 100644
index 0000000..381dc73
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/.classpath
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+ <classpathentry kind="src" path="src/main/java"/>
+ <classpathentry kind="src" path="src/test/resources"/>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
+ <classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/.gitignore b/org.eclipse.lyo.oslc4j.bugzilla.trs/.gitignore
new file mode 100644
index 0000000..db5a91d
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/.gitignore
@@ -0,0 +1,7 @@
+/target
+/RDFStore
+/bin
+/bugzillaOAuthStore.xml
+/consumerStore
+
+/derby.log
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/.project b/org.eclipse.lyo.oslc4j.bugzilla.trs/.project
new file mode 100644
index 0000000..30137b7
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/.project
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.lyo.oslc4j.bugzilla.trs</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.wst.validation.validationbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+ <nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ <nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/.jsdtscope b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/.jsdtscope
new file mode 100644
index 0000000..fac399c
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/webapp"/>
+ <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
+ <attributes>
+ <attribute name="hide" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
+ <classpathentry kind="output" path=""/>
+</classpath>
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3a00b27
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+#Tue Apr 03 16:25:04 EDT 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.m2e.core.prefs b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..93ed0ea
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,5 @@
+#Tue Apr 03 16:21:47 EDT 2012
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.common.component b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..99a83f8
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+ <wb-module deploy-name="org.eclipse.lyo.oslc4j.bugzilla.trs">
+ <wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
+ <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
+ <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
+ <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/resources"/>
+ <property name="java-output-path" value="/org.eclipse.lyo.oslc4j.bugzilla.trs/target/classes"/>
+ <property name="context-root" value="OSLC4JBugzilla"/>
+ </wb-module>
+</project-modules> \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.common.project.facet.core.xml b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..46602db
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+ <fixed facet="wst.jsdt.web"/>
+ <installed facet="java" version="1.6"/>
+ <installed facet="jst.web" version="3.0"/>
+ <installed facet="wst.jsdt.web" version="1.0"/>
+</faceted-project>
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.jsdt.ui.superType.container b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.jsdt.ui.superType.name b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/TRS-SDK.pdf b/org.eclipse.lyo.oslc4j.bugzilla.trs/TRS-SDK.pdf
new file mode 100644
index 0000000..a832d5f
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/TRS-SDK.pdf
Binary files differ
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/about.html b/org.eclipse.lyo.oslc4j.bugzilla.trs/about.html
new file mode 100644
index 0000000..e0fbbb2
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/about.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>About</title>
+</head>
+<body lang="EN-US">
+ <h2>About This Content</h2>
+ <p>13 December, 2011</p>
+ <h3>License</h3>
+ <p>
+ The Eclipse Foundation makes available all content in this plug-in
+ (&quot;Content&quot;). Unless otherwise indicated below, the Content
+ is provided to you under the terms and conditions of the Eclipse
+ Public License Version 1.0 (&quot;EPL&quot;) and Eclipse Distribution
+ License Version 1.0 (&quot;EDL&quot;). A copy of the EPL is available
+ at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>
+ and a copy of the EDL is available at <a
+ href="http://www.eclipse.org/org/documents/edl-v10.php">http://www.eclipse.org/org/documents/edl-v10.php</a>.
+ For purposes of the EPL, &quot;Program&quot; will mean the Content.
+ </p>
+ <p>If you did not receive this Content directly from the Eclipse
+ Foundation, the Content is being redistributed by another party
+ (&quot;Redistributor&quot;) and different terms and conditions may
+ apply to your use of any object code in the Content. Check the
+ Redistributor's license that was provided with the Content. If no such
+ license exists, contact the Redistributor. Unless otherwise indicated
+ below, the terms and conditions of the EPL and EDL still apply to any
+ source code in the Content and such source code may be obtained at
+ <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/license/edl-v10.html b/org.eclipse.lyo.oslc4j.bugzilla.trs/license/edl-v10.html
new file mode 100644
index 0000000..26b0770
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/license/edl-v10.html
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Distribution License - Version 1.0</title>
+<style type="text/css">
+ body {
+ size: 8.5in 11.0in;
+ margin: 0.25in 0.5in 0.25in 0.5in;
+ tab-interval: 0.5in;
+ }
+ p {
+ margin-left: auto;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ }
+ p.list {
+ margin-left: 0.5in;
+ margin-top: 0.05em;
+ margin-bottom: 0.05em;
+ }
+ </style>
+
+</head>
+
+<body lang="EN-US">
+
+<p><b>Eclipse Distribution License - v 1.0</b></p>
+
+<p>Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors. </p>
+
+<p>All rights reserved.</p>
+<p>Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+<ul><li>Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer. </li>
+<li>Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution. </li>
+<li>Neither the name of the Eclipse Foundation, Inc. nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission. </li></ul>
+</p>
+<p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.</p>
+
+</body>
+
+</html>
+
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/license/epl-v10.html b/org.eclipse.lyo.oslc4j.bugzilla.trs/license/epl-v10.html
new file mode 100644
index 0000000..1107453
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/license/epl-v10.html
@@ -0,0 +1,259 @@
+<!--?xml version="1.0" encoding="ISO-8859-1" ?-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"><head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Eclipse Public License - Version 1.0</title>
+<style type="text/css">
+ body {
+ size: 8.5in 11.0in;
+ margin: 0.25in 0.5in 0.25in 0.5in;
+ tab-interval: 0.5in;
+ }
+ p {
+ margin-left: auto;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ }
+ p.list {
+ margin-left: 0.5in;
+ margin-top: 0.05em;
+ margin-bottom: 0.05em;
+ }
+ </style>
+
+</head>
+
+<body lang="EN-US">
+
+<h2>Eclipse Public License - v 1.0</h2>
+
+<p>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR
+DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
+AGREEMENT.</p>
+
+<p><b>1. DEFINITIONS</b></p>
+
+<p>"Contribution" means:</p>
+
+<p class="list">a) in the case of the initial Contributor, the initial
+code and documentation distributed under this Agreement, and</p>
+<p class="list">b) in the case of each subsequent Contributor:</p>
+<p class="list">i) changes to the Program, and</p>
+<p class="list">ii) additions to the Program;</p>
+<p class="list">where such changes and/or additions to the Program
+originate from and are distributed by that particular Contributor. A
+Contribution 'originates' from a Contributor if it was added to the
+Program by such Contributor itself or anyone acting on such
+Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii)
+are not derivative works of the Program.</p>
+
+<p>"Contributor" means any person or entity that distributes
+the Program.</p>
+
+<p>"Licensed Patents" mean patent claims licensable by a
+Contributor which are necessarily infringed by the use or sale of its
+Contribution alone or when combined with the Program.</p>
+
+<p>"Program" means the Contributions distributed in accordance
+with this Agreement.</p>
+
+<p>"Recipient" means anyone who receives the Program under
+this Agreement, including all Contributors.</p>
+
+<p><b>2. GRANT OF RIGHTS</b></p>
+
+<p class="list">a) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free copyright license to reproduce, prepare derivative works
+of, publicly display, publicly perform, distribute and sublicense the
+Contribution of such Contributor, if any, and such derivative works, in
+source code and object code form.</p>
+
+<p class="list">b) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell,
+offer to sell, import and otherwise transfer the Contribution of such
+Contributor, if any, in source code and object code form. This patent
+license shall apply to the combination of the Contribution and the
+Program if, at the time the Contribution is added by the Contributor,
+such addition of the Contribution causes such combination to be covered
+by the Licensed Patents. The patent license shall not apply to any other
+combinations which include the Contribution. No hardware per se is
+licensed hereunder.</p>
+
+<p class="list">c) Recipient understands that although each Contributor
+grants the licenses to its Contributions set forth herein, no assurances
+are provided by any Contributor that the Program does not infringe the
+patent or other intellectual property rights of any other entity. Each
+Contributor disclaims any liability to Recipient for claims brought by
+any other entity based on infringement of intellectual property rights
+or otherwise. As a condition to exercising the rights and licenses
+granted hereunder, each Recipient hereby assumes sole responsibility to
+secure any other intellectual property rights needed, if any. For
+example, if a third party patent license is required to allow Recipient
+to distribute the Program, it is Recipient's responsibility to acquire
+that license before distributing the Program.</p>
+
+<p class="list">d) Each Contributor represents that to its knowledge it
+has sufficient copyright rights in its Contribution, if any, to grant
+the copyright license set forth in this Agreement.</p>
+
+<p><b>3. REQUIREMENTS</b></p>
+
+<p>A Contributor may choose to distribute the Program in object code
+form under its own license agreement, provided that:</p>
+
+<p class="list">a) it complies with the terms and conditions of this
+Agreement; and</p>
+
+<p class="list">b) its license agreement:</p>
+
+<p class="list">i) effectively disclaims on behalf of all Contributors
+all warranties and conditions, express and implied, including warranties
+or conditions of title and non-infringement, and implied warranties or
+conditions of merchantability and fitness for a particular purpose;</p>
+
+<p class="list">ii) effectively excludes on behalf of all Contributors
+all liability for damages, including direct, indirect, special,
+incidental and consequential damages, such as lost profits;</p>
+
+<p class="list">iii) states that any provisions which differ from this
+Agreement are offered by that Contributor alone and not by any other
+party; and</p>
+
+<p class="list">iv) states that source code for the Program is available
+from such Contributor, and informs licensees how to obtain it in a
+reasonable manner on or through a medium customarily used for software
+exchange.</p>
+
+<p>When the Program is made available in source code form:</p>
+
+<p class="list">a) it must be made available under this Agreement; and</p>
+
+<p class="list">b) a copy of this Agreement must be included with each
+copy of the Program.</p>
+
+<p>Contributors may not remove or alter any copyright notices contained
+within the Program.</p>
+
+<p>Each Contributor must identify itself as the originator of its
+Contribution, if any, in a manner that reasonably allows subsequent
+Recipients to identify the originator of the Contribution.</p>
+
+<p><b>4. COMMERCIAL DISTRIBUTION</b></p>
+
+<p>Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use of
+the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create
+potential liability for other Contributors. Therefore, if a Contributor
+includes the Program in a commercial product offering, such Contributor
+("Commercial Contributor") hereby agrees to defend and
+indemnify every other Contributor ("Indemnified Contributor")
+against any losses, damages and costs (collectively "Losses")
+arising from claims, lawsuits and other legal actions brought by a third
+party against the Indemnified Contributor to the extent caused by the
+acts or omissions of such Commercial Contributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In
+order to qualify, an Indemnified Contributor must: a) promptly notify
+the Commercial Contributor in writing of such claim, and b) allow the
+Commercial Contributor to control, and cooperate with the Commercial
+Contributor in, the defense and any related settlement negotiations. The
+Indemnified Contributor may participate in any such claim at its own
+expense.</p>
+
+<p>For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those
+performance claims and warranties, and if a court requires any other
+Contributor to pay any damages as a result, the Commercial Contributor
+must pay those damages.</p>
+
+<p><b>5. NO WARRANTY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
+ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to
+the risks and costs of program errors, compliance with applicable laws,
+damage to or loss of data, programs or equipment, and unavailability or
+interruption of operations.</p>
+
+<p><b>6. DISCLAIMER OF LIABILITY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
+NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p>
+
+<p><b>7. GENERAL</b></p>
+
+<p>If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further action
+by the parties hereto, such provision shall be reformed to the minimum
+extent necessary to make such provision valid and enforceable.</p>
+
+<p>If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other
+software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the
+date such litigation is filed.</p>
+
+<p>All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of time
+after becoming aware of such noncompliance. If all Recipient's rights
+under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive.</p>
+
+<p>Everyone is permitted to copy and distribute copies of this
+Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The
+Agreement Steward reserves the right to publish new versions (including
+revisions) of this Agreement from time to time. No one other than the
+Agreement Steward has the right to modify this Agreement. The Eclipse
+Foundation is the initial Agreement Steward. The Eclipse Foundation may
+assign the responsibility to serve as the Agreement Steward to a
+suitable separate entity. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version
+of the Agreement is published, Contributor may elect to distribute the
+Program (including its Contributions) under the new version. Except as
+expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
+rights or licenses to the intellectual property of any Contributor under
+this Agreement, whether expressly, by implication, estoppel or
+otherwise. All rights in the Program not expressly granted under this
+Agreement are reserved.</p>
+
+<p>This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No party
+to this Agreement will bring a legal action under this Agreement more
+than one year after the cause of action arose. Each party waives its
+rights to a jury trial in any resulting litigation.</p>
+
+
+
+</body></html> \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/license/notice.html b/org.eclipse.lyo.oslc4j.bugzilla.trs/license/notice.html
new file mode 100644
index 0000000..80720cd
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/license/notice.html
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Foundation Software User Agreement</title>
+</head>
+
+<body lang="EN-US">
+<h2>Eclipse Foundation Software User Agreement</h2>
+<p>13 December, 2011</p>
+
+<h3>Usage Of Content</h3>
+
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+ (COLLECTIVELY &quot;CONTENT&quot;). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+ CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+ OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+ NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+ CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
+
+<h3>Applicable Licenses</h3>
+
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+ (&quot;EPL&quot;). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+ For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
+ repository (&quot;Repository&quot;) in software modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p>
+
+<ul>
+ <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li>
+ <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li>
+ <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;. Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
+ and/or Fragments associated with that Feature.</li>
+ <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li>
+</ul>
+
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
+Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;). Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p>
+
+<ul>
+ <li>The top-level (root) directory</li>
+ <li>Plug-in and Fragment directories</li>
+ <li>Inside Plug-ins and Fragments packaged as JARs</li>
+ <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li>
+ <li>Feature directories</li>
+</ul>
+
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license (&quot;Feature Update License&quot;) during the
+installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them. Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p>
+
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
+
+<ul>
+ <li>Eclipse Distribution License Version 1.0 (available at <a href="http://www.eclipse.org/licenses/edl-v10.html">http://www.eclipse.org/licenses/edl-v1.0.html</a>)</li>
+ <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
+ <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
+ <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+ <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li>
+ <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
+</ul>
+
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
+
+
+<h3>Use of Provisioning Technology</h3>
+
+<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
+ Update Manager (&quot;Provisioning Technology&quot;) for the purpose of allowing users to install software, documentation, information and/or
+ other materials (collectively &quot;Installable Software&quot;). This capability is provided with the intent of allowing such users to
+ install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a
+ href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a>
+ (&quot;Specification&quot;).</p>
+
+<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
+ applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
+ in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
+ Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p>
+
+<ol>
+ <li>A series of actions may occur (&quot;Provisioning Process&quot;) in which a user may execute the Provisioning Technology
+ on a machine (&quot;Target Machine&quot;) with the intent of installing, extending or updating the functionality of an Eclipse-based
+ product.</li>
+ <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
+ accessed and copied to the Target Machine.</li>
+ <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
+ Software (&quot;Installable Software Agreement&quot;) and such Installable Software Agreement shall be accessed from the Target
+ Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
+ the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
+ indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li>
+</ol>
+
+<h3>Cryptography</h3>
+
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+ another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+ possession, or use, and re-export of encryption software, to see if this is permitted.</p>
+
+<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p>
+</body>
+</html>
+
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/pom.xml b/org.eclipse.lyo.oslc4j.bugzilla.trs/pom.xml
new file mode 100644
index 0000000..506d0f9
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/pom.xml
@@ -0,0 +1,132 @@
+<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.eclipse.lyo.oslc4j.rio</groupId>
+ <artifactId>trs4j-bugzilla-sample</artifactId>
+ <packaging>war</packaging>
+ <version>0.0.1-SNAPSHOT</version>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.0.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.lyo</groupId>
+ <artifactId>oslc-trs</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.lyo.oslc4j.core</groupId>
+ <artifactId>oslc4j-json4j-provider</artifactId>
+ <version>[1.1-SNAPSHOT,)</version>
+ </dependency>
+ <dependency>
+ <groupId>com.j2bugzilla</groupId>
+ <artifactId>j2bugzilla</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.lyo.server</groupId>
+ <artifactId>oauth-webapp</artifactId>
+ <version>[1.1-SNAPSHOT,)</version>
+ <type>war</type>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.lyo.server</groupId>
+ <artifactId>oauth-core</artifactId>
+ <version>[1.1-SNAPSHOT,)</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.lyo.server</groupId>
+ <artifactId>oauth-consumer-store</artifactId>
+ <version>[1.1-SNAPSHOT,)</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.lyo.core.query</groupId>
+ <artifactId>oslc-query</artifactId>
+ <version>[1.1,)</version>
+ </dependency>
+
+ <dependency>
+ <groupId>taglibs</groupId>
+ <artifactId>standard</artifactId>
+ <version>1.1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>jstl</groupId>
+ <artifactId>jstl</artifactId>
+ <version>1.1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>javax.servlet.jsp-api</artifactId>
+ <version>2.2.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.2.1</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>trs4j-bugzilla-sample</finalName>
+ <plugins>
+
+ <!-- Jetty 7 plugin See also: http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin -->
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ <!-- <version>7.3.0.v20110203</version> -->
+
+ <configuration>
+ <webAppConfig>
+ <contextPath>/OSLC4JBugzilla</contextPath>
+ </webAppConfig>
+
+ <!-- Jetty config adds logging -->
+ <jettyConfig>${project.build.directory}/classes/jetty.xml</jettyConfig>
+
+ <!-- enable hot deploy -->
+ <reload>automatic</reload>
+ <scanIntervalSeconds>5</scanIntervalSeconds>
+ <scanTargets>
+ <scanTarget>WebContent</scanTarget>
+ </scanTargets>
+
+ <systemProperties>
+
+ <systemProperty>
+ <name>config.dir</name>
+ <value>${basedir}/src/test/resources</value>
+ </systemProperty>
+
+ <systemProperty>
+ <name>jetty.logs</name>
+ <value>${basedir}/target</value>
+ </systemProperty>
+ <systemProperty>
+ <name>jetty.port</name>
+ <value>8085</value>
+ </systemProperty>
+ </systemProperties>
+
+ </configuration>
+
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/BugzillaManager.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/BugzillaManager.java
new file mode 100644
index 0000000..404bcb3
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/BugzillaManager.java
@@ -0,0 +1,1053 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Sam Padgett - initial API and implementation
+ * Michael Fiedler - adapted for OSLC4J
+ *******************************************************************************/
+
+package org.eclipse.lyo.oslc4j.bugzilla;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.net.UnknownHostException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.eclipse.lyo.core.query.ComparisonTerm;
+import org.eclipse.lyo.core.query.CompoundTerm;
+import org.eclipse.lyo.core.query.InTerm;
+import org.eclipse.lyo.core.query.OrderByClause;
+import org.eclipse.lyo.core.query.PName;
+import org.eclipse.lyo.core.query.ParseException;
+import org.eclipse.lyo.core.query.QueryUtils;
+import org.eclipse.lyo.core.query.ScopedSortTerm;
+import org.eclipse.lyo.core.query.SimpleSortTerm;
+import org.eclipse.lyo.core.query.SimpleTerm;
+import org.eclipse.lyo.core.query.SortTerm;
+import org.eclipse.lyo.core.query.SortTerms;
+import org.eclipse.lyo.core.query.Value;
+import org.eclipse.lyo.core.query.WhereClause;
+import org.eclipse.lyo.oslc4j.bugzilla.resources.BugzillaChangeRequest;
+import org.eclipse.lyo.oslc4j.bugzilla.resources.Person;
+import org.eclipse.lyo.oslc4j.bugzilla.servlet.CredentialsFilter;
+import org.eclipse.lyo.oslc4j.bugzilla.servlet.ServiceProviderCatalogSingleton;
+import org.eclipse.lyo.oslc4j.bugzilla.trs.GetComments;
+import org.eclipse.lyo.oslc4j.bugzilla.trs.GetHistory;
+import org.eclipse.lyo.oslc4j.bugzilla.trs.HistoryData;
+import org.eclipse.lyo.oslc4j.bugzilla.utils.BugzillaHttpClient;
+import org.eclipse.lyo.oslc4j.client.ServiceProviderRegistryURIs;
+import org.eclipse.lyo.oslc4j.core.SingletonWildcardProperties;
+import org.eclipse.lyo.oslc4j.core.model.Link;
+import org.eclipse.lyo.oslc4j.core.model.OslcConstants;
+import org.eclipse.lyo.oslc4j.core.model.ServiceProvider;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import com.j2bugzilla.base.Bug;
+import com.j2bugzilla.base.BugFactory;
+import com.j2bugzilla.base.BugzillaConnector;
+import com.j2bugzilla.base.Product;
+import com.j2bugzilla.rpc.CommentBug;
+import com.j2bugzilla.rpc.GetBug;
+import com.j2bugzilla.rpc.GetProduct;
+import com.j2bugzilla.rpc.ReportBug;
+
+
+public class BugzillaManager implements ServletContextListener {
+
+ public final static String REALM = "Bugzilla";
+
+ private static String bugzillaUri = null;
+ private static String admin = null;
+ private static String admin_password = null; // Added in Lab 1.2
+ private static String adapter_host = null; // Added in Lab 1.2
+
+ private static String servletBase = null;
+ private static String bugzServiceBase = null;
+
+ private static final String BUGZ_SERVICE_PATH = "/services";
+ private static final String PROPERTY_SCHEME = BugzillaManager.class.getPackage().getName() + ".scheme";
+ private static final String PROPERTY_PORT = BugzillaManager.class.getPackage().getName() + ".port";
+ private static final String SYSTEM_PROPERTY_NAME_REGISTRY_URI = ServiceProviderRegistryURIs.class.getPackage().getName() + ".registryuri";
+ private static final String QUERY_PREFIX =
+ "buglist.cgi?query_format=advanced&ctype=rdf&columnlist=" +
+ "short_desc," +
+ "bug_status," +
+ "assigned_to," +
+ "product," +
+ "component," +
+ "version," +
+ "priority," +
+ "rep_platform," +
+ "op_sys";
+ private static final String BUGZ_NS = "http://www.bugzilla.org/rdf#";
+ private static final String BUGZ_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss Z";
+
+ private static QName OSLC_SCORE = new QName(OslcConstants.OSLC_CORE_NAMESPACE, "score");
+
+ //Bugzilla adapter properties from bugz.properties
+ static {
+ Properties props = new Properties();
+ try {
+ props.load(BugzillaManager.class.getResourceAsStream("/bugz.properties"));
+ bugzillaUri = props.getProperty("bugzilla_uri");
+ admin = props.getProperty("admin");
+ admin_password = props.getProperty("admin_password", ""); // Added in Lab 1.2
+ adapter_host = props.getProperty("adapter_host"); // Added in Lab 1.2
+ System.out.println("bugzilla_uri: " + bugzillaUri);
+ System.out.println("admin: " + admin);
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ private static final String HOST = getHost();
+
+ @Override
+ public void contextDestroyed(ServletContextEvent servletContextEvent)
+ {
+ //No need to de-register - catalog will go away with the web app
+ }
+
+ @Override
+ public void contextInitialized(final ServletContextEvent servletContextEvent)
+ {
+ //Get the servlet base URI and set some paths to the REST services and the catalog
+ String basePath=generateBasePath(servletContextEvent);
+ servletBase = basePath;
+ bugzServiceBase = basePath + BUGZ_SERVICE_PATH;
+ System.setProperty(SYSTEM_PROPERTY_NAME_REGISTRY_URI, basePath + BUGZ_SERVICE_PATH + "/catalog/singleton");
+ }
+
+ /**
+ * get BugzillaConnector from the HttpSession
+ *
+ * The connector should be placed in the session by the CredentialsFilter servlet filter
+ *
+ * @param request
+ * @return connector
+ */
+ public static BugzillaConnector getBugzillaConnector(HttpServletRequest request)
+ {
+ //connector should never be null if CredentialsFilter is doing its job
+ BugzillaConnector connector = CredentialsFilter.getConnector(request);
+ return connector;
+ }
+
+
+ private static String generateBasePath(final ServletContextEvent servletContextEvent)
+ {
+ final ServletContext servletContext = servletContextEvent.getServletContext();
+
+ String scheme = System.getProperty(PROPERTY_SCHEME);
+ if (scheme == null)
+ {
+ scheme = servletContext.getInitParameter(PROPERTY_SCHEME);
+ }
+
+ String port = System.getProperty(PROPERTY_PORT);
+ if (port == null)
+ {
+ port = servletContext.getInitParameter(PROPERTY_PORT);
+ }
+
+ return scheme + "://" + HOST + ":" + port + servletContext.getContextPath();
+ }
+
+ /*
+ * Modified in Lab 1.2
+ */
+ private static String getHost()
+ {
+ if (adapter_host != null)
+ {
+ return adapter_host;
+ }
+
+ try
+ {
+ return InetAddress.getLocalHost().getCanonicalHostName();
+ }
+ catch (final UnknownHostException exception)
+ {
+ return "localhost";
+ }
+ }
+
+
+ public static String getBugzillaUri() {
+ return bugzillaUri;
+ }
+
+ public static void setBugzillaUri(String bugzillaUri) {
+ BugzillaManager.bugzillaUri = bugzillaUri;
+ }
+
+ public static String getServletBase() {
+ return servletBase;
+ }
+
+ public static String getBugzServiceBase() {
+ return bugzServiceBase;
+ }
+
+ public static String getAdmin() {
+ return admin;
+ }
+
+ /*
+ * Added in Lab 1.2
+ */
+ public static Credentials getAdminCredentials() {
+ Credentials result = new Credentials();
+ result.setUsername(getAdmin());
+ result.setPassword(admin_password);
+ return result;
+ }
+
+ //The following are static utility methods are useful for getting, creating and updating Bugzilla bugs. Primarily used by BugzillaChangeRequestService
+
+ /**
+ * Create a list of Bugs for a product ID using paging
+ *
+ * @param httpServletRequest
+ * @param productIdString
+ * @param page
+ * @param limit
+ * @param oslcWhere
+ * @param prefixMap
+ * @param propMap
+ * @param orderBy
+ * @param searchTerms
+ *
+ * @return The list of change requests, paged if necessary
+ *
+ * @throws IOException
+ * @throws ServletException
+ */
+ public static List<BugzillaChangeRequest>
+ getBugsByProduct(final HttpServletRequest httpServletRequest,
+ final String productIdString,
+ int page,
+ int limit,
+ String oslcWhere,
+ Map<String, String> prefixMap,
+ Map<String, Object> propMap,
+ String orderBy,
+ String searchTerms) throws IOException, ServletException
+ {
+ List<BugzillaChangeRequest> results=new ArrayList<BugzillaChangeRequest>();
+
+ try {
+
+ final BugzillaConnector bc = BugzillaManager.getBugzillaConnector(httpServletRequest);
+
+ if (bc != null) {
+
+ final ServiceProvider serviceProvider =
+ ServiceProviderCatalogSingleton.getServiceProvider(
+ httpServletRequest, productIdString);
+ StringBuffer buffer = new StringBuffer();
+
+ boolean fulltextSearch = searchTerms != null &&
+ searchTerms.length() != 0;
+
+ buffer.append(QUERY_PREFIX);
+
+ if (fulltextSearch) {
+
+ buffer.append(",relevance&content=");
+
+ boolean first = true;
+
+ for (String searchTerm : QueryUtils.parseSearchTerms(searchTerms)) {
+
+ if (first) {
+ first = false;
+ } else {
+ buffer.append('+');
+ }
+
+ buffer.append(URLEncoder.encode('"' + searchTerm + '"', "UTF-8"));
+ }
+ }
+
+ createBugSearch(page, limit, serviceProvider, oslcWhere, prefixMap, buffer);
+
+ if (orderBy != null && orderBy.length() != 0) {
+
+ OrderByClause orderByClause =
+ QueryUtils.parseOrderBy(orderBy, prefixMap);
+
+ buffer.append("&order=");
+
+ if (fulltextSearch) {
+ buffer.append("relevance+DESC");
+ }
+
+ addSort(buffer, orderByClause, toplevelQueryProperties, ! fulltextSearch);
+
+ } else if (fulltextSearch) {
+
+ buffer.append("&order=relevance+DESC");
+
+ } else {
+
+ // Always order at least by bug id, so we get
+ // non-random returns across pages
+ buffer.append("&order=bug_id");
+ }
+
+ Credentials credentials = CredentialsFilter.getCredentials(httpServletRequest);
+
+ BugzillaHttpClient client = new BugzillaHttpClient(getBugzillaUri(), credentials);
+
+ InputStream response = client.httpGet(buffer.toString());
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document document = builder.parse(response);
+ Element root = document.getDocumentElement();
+ NodeList list = root.getElementsByTagNameNS(BUGZ_NS, "bug");
+
+ factory.setNamespaceAware(false);
+
+ builder = factory.newDocumentBuilder();
+
+ int length = list.getLength();
+
+ if (length > limit) {
+ httpServletRequest.setAttribute(Constants.NEXT_PAGE, page + 1);
+ length--;
+ }
+
+ for (int idx = 0; idx < length; idx++) {
+
+ Element p = (Element)list.item(idx);
+
+ BugzillaChangeRequest changeRequest =
+ createChangeRequest(p, fulltextSearch);
+
+ if (propMap instanceof SingletonWildcardProperties ||
+ propMap.get(OslcConstants.DCTERMS_NAMESPACE + "created") != null ||
+ propMap.get(OslcConstants.DCTERMS_NAMESPACE + "modified") != null) {
+
+ buffer = new StringBuffer();
+
+ buffer.append("show_bug.cgi?id=");
+ buffer.append(changeRequest.getIdentifier());
+ buffer.append("&ctype=xml&field=creation_ts&field=delta_ts");
+
+ response = client.httpGet(buffer.toString());
+
+ document = builder.parse(response);
+ root = document.getDocumentElement();
+
+ NodeList innerList = root.getElementsByTagName("creation_ts");
+
+ if (innerList.getLength() == 1) {
+ changeRequest.setCreated(convertBugzillaDate(innerList.item(0).getTextContent()));
+ }
+
+ innerList = root.getElementsByTagName("delta_ts");
+
+ if (innerList.getLength() == 1) {
+ changeRequest.setModified(convertBugzillaDate(innerList.item(0).getTextContent()));
+ }
+ }
+
+ changeRequest.setServiceProvider(ServiceProviderCatalogSingleton.getServiceProvider(httpServletRequest, productIdString).getAbout());
+
+ URI about;
+
+ try {
+ about = new URI(getBugzServiceBase() + "/" + productIdString + "/changeRequests/"+ changeRequest.getIdentifier());
+ } catch (URISyntaxException e) {
+ throw new WebApplicationException(e);
+ }
+
+ changeRequest.setAbout(about);
+
+ results.add(changeRequest);
+ }
+
+ } else {
+ System.err.println("Bugzilla Connector not initialized - check bugz.properties");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw ((e instanceof WebApplicationException) ?
+ (WebApplicationException)e :
+ new WebApplicationException(e));
+ }
+
+ return results;
+ }
+
+ private static Date convertBugzillaDate(String dateString) throws IOException
+ {
+ if (dateString == null) {
+ return null;
+ }
+
+ DateFormat format = new SimpleDateFormat(BUGZ_DATE_FORMAT);
+
+ try {
+ return format.parse(dateString);
+ } catch (java.text.ParseException e) {
+ throw new IOException(e);
+ }
+ }
+
+ private static BugzillaChangeRequest createChangeRequest(Element bug, boolean fulltextSearch) throws IOException, URISyntaxException
+ {
+ BugzillaChangeRequest changeRequest = new BugzillaChangeRequest();
+
+ changeRequest.setIdentifier(elementText(bug, "id"));
+ changeRequest.setTitle(elementText(bug, "short_desc"));
+ changeRequest.setStatus(elementText(bug, "bug_status"));
+
+ //Map contributor to the person this bug is assigned to
+ String email = elementText(bug, "assigned_to");
+ if (email != null) {
+ Person contributor = new Person();
+ contributor.setUri(new URI(BugzillaManager.getServletBase() + "/person?mbox=" + URLEncoder.encode(email, "UTF-8")));
+ contributor.setMbox(email);
+ contributor.setAbout(contributor.getUri());
+ ArrayList<Person> contributors = new ArrayList<Person>();
+ contributors.add(contributor);
+ changeRequest.setContributors(contributors);
+ }
+
+ changeRequest.setProduct(elementText(bug, "product"));
+ changeRequest.setComponent(elementText(bug, "component"));
+ changeRequest.setVersion(elementText(bug, "version"));
+ changeRequest.setPriority(elementText(bug, "priority"));
+ changeRequest.setPlatform(elementText(bug, "rep_platform"));
+ changeRequest.setOperatingSystem(elementText(bug, "op_sys"));
+
+ if (fulltextSearch) {
+
+ String relevance = elementText(bug, "relevance");
+
+ if (relevance != null) {
+
+ Map<QName, Object> extProps = new HashMap<QName, Object>(1);
+
+ extProps.put(OSLC_SCORE, Float.valueOf(relevance));
+
+ changeRequest.setExtendedProperties(extProps);
+ }
+ }
+
+ return changeRequest;
+ }
+
+ private static String elementText(Element parent, String localName)
+ {
+ NodeList list = parent.getElementsByTagNameNS(BUGZ_NS, localName);
+
+ if (list.getLength() > 1) {
+ throw new IllegalStateException("More than one " + BUGZ_NS +
+ localName + " child");
+ }
+
+ return list.getLength() == 0 ? null : list.item(0).getTextContent();
+ }
+
+ private static void createBugSearch(int page, int limit, final ServiceProvider serviceProvider , String oslcWhere,
+ Map<String, String> prefixMap, final StringBuffer buffer) throws ParseException
+ {
+ buffer.append("&limit=");
+ buffer.append(limit + 1);
+
+ buffer.append("&offset=");
+ buffer.append(page * limit);
+
+ addSearchTerm(0, "product", "equals", serviceProvider.getTitle(), buffer);
+
+ if (oslcWhere != null) {
+
+ WhereClause whereClause = QueryUtils.parseWhere(oslcWhere, prefixMap);
+
+ createSearchQueries(buffer, 1, whereClause, toplevelQueryProperties);
+ }
+ }
+
+ private static void
+ addSearchTerm(int index, String field, String operator, String value,
+ final StringBuffer buffer)
+ {
+ buffer.append("&field");
+ buffer.append(index);
+ buffer.append("-0-0=");
+ buffer.append(field);
+
+ buffer.append("&type");
+ buffer.append(index);
+ buffer.append("-0-0=");
+ buffer.append(operator);
+
+ buffer.append("&value");
+ buffer.append(index);
+ buffer.append("-0-0=");
+
+ try {
+ buffer.append(URLEncoder.encode(value, "UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ // XXX - can't happen
+ }
+ }
+
+ private static int createSearchQueries(final StringBuffer buffer, int index,
+ CompoundTerm compoundTerm,
+ Map<String, Object> queryProperties)
+ {
+ for (SimpleTerm term : compoundTerm.children()) {
+
+ switch (term.type()) {
+ case COMPARISON:
+ break;
+ case NESTED:
+ PName property = term.property();
+ Object field = queryProperties.get(property.namespace + property.local);
+
+ if (field == null || field instanceof String) {
+ throw new WebApplicationException(
+ new UnsupportedOperationException("Unsupported oslc.where nested term property term: " + term),
+ Status.BAD_REQUEST);
+ }
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> nestedQueryProperties = (Map<String, Object>)field;
+
+ index = createSearchQueries(buffer, index, (CompoundTerm)term, nestedQueryProperties);
+
+ continue;
+
+ default:
+ createInQuery(buffer, index++, (InTerm)term, queryProperties);
+ continue;
+ }
+
+ ComparisonTerm comparison = (ComparisonTerm)term;
+ String operator;
+
+ switch (comparison.operator()) {
+ case EQUALS:
+ operator = "equals";
+ break;
+ case NOT_EQUALS:
+ operator = "notequals";
+ break;
+ case LESS_THAN:
+ operator = "lessthan";
+ break;
+ case LESS_EQUALS:
+ operator = "lessthaneq";
+ break;
+ case GREATER_THAN:
+ operator = "greaterthan";
+ break;
+ default:
+ case GREATER_EQUALS:
+ operator = "greaterhaneq";
+ break;
+ }
+
+ PName property = comparison.property();
+ Object field =
+ queryProperties.get(property.namespace + property.local);
+
+ if (field == null || ! (field instanceof String)) {
+ throw new WebApplicationException(
+ new UnsupportedOperationException("Unsupported oslc.where comparison property: " + term),
+ Status.BAD_REQUEST);
+ }
+
+ Value operand = comparison.operand();
+ String value = operand.toString();
+
+ switch (operand.type()) {
+ case STRING:
+ case URI_REF:
+ value = value.substring(1, value.length() - 1);
+ break;
+ case BOOLEAN:
+ case DECIMAL:
+ break;
+ default:
+ throw new WebApplicationException(
+ new UnsupportedOperationException("Unsupported oslc.where comparison operand: " + value),
+ Status.BAD_REQUEST);
+ }
+
+ addSearchTerm(index++, (String)field, operator, value, buffer);
+ }
+
+ return index;
+ }
+
+ private static void addSort(final StringBuffer buffer,
+ final SortTerms orderByClause,
+ final Map<String, Object> queryProperties,
+ boolean first)
+ {
+ for (SortTerm term : orderByClause.children()) {
+
+ switch (term.type())
+ {
+ case SIMPLE:
+ break;
+ case SCOPED:
+ PName property = term.identifier();
+ Object field = queryProperties.get(property.namespace
+ + property.local);
+
+ if (field == null || field instanceof String) {
+ throw new WebApplicationException(
+ new UnsupportedOperationException(
+ "Unsupported oslc.orderBy scoped term sort term: "
+ + term), Status.BAD_REQUEST);
+ }
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> nestedQueryProperties = (Map<String, Object>) field;
+
+ addSort(buffer, ((ScopedSortTerm) term).sortTerms(),
+ nestedQueryProperties, first);
+
+ first = false;
+
+ continue;
+ }
+
+ PName property = term.identifier();
+ Object field = queryProperties.get(property.namespace
+ + property.local);
+
+ if (field == null || !(field instanceof String)) {
+ throw new WebApplicationException(
+ new UnsupportedOperationException(
+ "Unsupported oslc.orderBy property: "
+ + term), Status.BAD_REQUEST);
+ }
+
+ if (first) {
+ first = false;
+ } else {
+ buffer.append(',');
+ }
+
+ buffer.append((String)field);
+
+ if (! ((SimpleSortTerm)term).ascending()) {
+ buffer.append("+DESC");
+ }
+ }
+ }
+
+ private static void createInQuery(final StringBuffer buffer, int index,
+ InTerm inTerm,
+ Map<String, Object> queryProperties)
+ {
+ PName property = inTerm.property();
+ Object field = queryProperties.get(property.namespace + property.local);
+
+ if (field == null || ! (field instanceof String)) {
+ throw new WebApplicationException(
+ new UnsupportedOperationException("Unsupported oslc.where comparison property: " + inTerm),
+ Status.BAD_REQUEST);
+ }
+
+ int subIndex = 0;
+
+ for (Value operand : inTerm.values()) {
+
+ String value = operand.toString();
+
+ switch (operand.type()) {
+ case STRING:
+ case URI_REF:
+ value = value.substring(1, value.length() - 1);
+ break;
+ case BOOLEAN:
+ case DECIMAL:
+ break;
+ default:
+ throw new WebApplicationException(
+ new UnsupportedOperationException("Unsupported oslc.where comparison operand: " + value),
+ Status.BAD_REQUEST);
+ }
+
+
+ buffer.append("&field");
+ buffer.append(index);
+ buffer.append("-0-");
+ buffer.append(subIndex);
+ buffer.append('=');
+ buffer.append(field);
+
+ buffer.append("&type");
+ buffer.append(index);
+ buffer.append("-0-");
+ buffer.append(subIndex);
+ buffer.append("=equals");
+
+ buffer.append("&value");
+ buffer.append(index);
+ buffer.append("-0-");
+ buffer.append(subIndex);
+ buffer.append('=');
+
+ try {
+ buffer.append(URLEncoder.encode(value, "UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ // XXX - can't happen
+ }
+
+ subIndex++;
+ }
+ }
+
+ /**
+ * Get a Bugzilla Bug by id
+ * @param request
+ * @param bugIdString
+ * @return Bug
+ * @throws IOException
+ * @throws ServletException
+ */
+ public static Bug getBugById(final HttpServletRequest request, final String bugIdString) throws IOException, ServletException
+ {
+ int bugId = -1;
+ Bug bug = null;
+
+ try {
+ bugId = Integer.parseInt(bugIdString);
+ final BugzillaConnector bc = BugzillaManager.getBugzillaConnector(request);
+ final GetBug getBug = new GetBug(bugId);
+ bc.executeMethod(getBug);
+ bug = getBug.getBug();
+ if (bug == null) {
+ throw new WebApplicationException(Status.NOT_FOUND);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new WebApplicationException(e);
+ }
+
+ return bug;
+ }
+
+ /*
+ * Added in Lab 1.3
+ */
+ /**
+ * Get a Bugzilla Bug History by id(and its Bug)
+ * @param request
+ * @param productIdString
+ * @param bugIdString
+ * @return Bug
+ * @throws IOException
+ * @throws ServletException
+ */
+ public static HistoryData[] getBugHistoryById(final HttpServletRequest request, final Bug bug, final String productIdString, final String bugIdString, final Date dayAfter) throws IOException, ServletException
+ {
+ try {
+ int bugId = Integer.parseInt(bugIdString);
+ final BugzillaConnector bc = BugzillaManager.getBugzillaConnector(request);
+ // get time stamps for "modified" : Bugzilla history
+ final GetHistory getHistory = new GetHistory(bugId);
+ bc.executeMethod(getHistory);
+ Date[] modifiedtimes_history = getHistory.getModifiedTimestamps(); // all is modified
+
+ // get time stamps for "modified" : Bugzilla comments
+ final GetComments getComments = new GetComments(bugId);
+ bc.executeMethod(getComments);
+ Date[] modifiedtimes_comments = getComments.getModifiedTimestamps(); // all is modified
+
+ // get OSLC URI. See org.eclipse.lyo.oslc4j.bugzilla.services.BugzillaChangeRequestService.createHtmlChangeRequest(String, String, String, String, String, String, String)
+ URI uri = new URI(BugzillaManager.getBugzServiceBase() + "/" + productIdString + "/changeRequests/" + bugIdString);
+
+ // get time stamp for "created"
+ Date creationtime = (Date)(bug.getParameterMap().get("creation_time"));
+// TODO;
+// On my environment, Bugzilla returns wrong incorrect time ( It seems to be always
+// GMT... )
+// String x = DateFormat.getDateTimeInstance(DateFormat.DEFAULT,
+// DateFormat.DEFAULT, Locale.getDefault()).format(o); // Looks like this seems to be GMT time
+// o.toString();
+ // build histories
+ List<HistoryData> result = new ArrayList<HistoryData>(modifiedtimes_history.length+modifiedtimes_comments.length+1);
+ for(Date t : modifiedtimes_history) {
+ if (dayAfter != null) {
+ if ( t.compareTo(dayAfter) > 0) {
+ result.add(HistoryData.getInstance(Integer.parseInt(productIdString), bugId, t, uri, HistoryData.MODIFIED));
+ }
+ } else {
+ result.add(HistoryData.getInstance(Integer.parseInt(productIdString), bugId, t, uri, HistoryData.MODIFIED));
+ }
+ }
+ for(Date t : modifiedtimes_comments) {
+ if (dayAfter != null) {
+ if ( t.compareTo(dayAfter) > 0) {
+ result.add(HistoryData.getInstance(Integer.parseInt(productIdString), bugId, t, uri, HistoryData.MODIFIED));
+ }
+ } else {
+ result.add(HistoryData.getInstance(Integer.parseInt(productIdString), bugId, t, uri, HistoryData.MODIFIED));
+ }
+ }
+ if (dayAfter != null) {
+ if ( creationtime.compareTo(dayAfter) > 0) {
+ result.add(HistoryData.getInstance(Integer.parseInt(productIdString), bugId, creationtime, uri, HistoryData.CREATED));
+ }
+ } else {
+ result.add(HistoryData.getInstance(Integer.parseInt(productIdString), bugId, creationtime, uri, HistoryData.CREATED));
+ }
+ HistoryData[] histories = new HistoryData[result.size()];
+ result.toArray(histories);
+ return histories;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new WebApplicationException(e);
+ }
+ }
+ /*
+ * Added in Lab 1.3
+ */
+ public static HistoryData[] getBugHistoryById(final HttpServletRequest request, final String productIdString, final String bugIdString, final Date dayAfter) throws IOException, ServletException {
+ try {
+ int bugId = Integer.parseInt(bugIdString);
+ final BugzillaConnector bc = BugzillaManager.getBugzillaConnector(request);
+ final GetBug getBug = new GetBug(bugId);
+ bc.executeMethod(getBug);
+ Bug bug = getBug.getBug();
+ if (bug == null) {
+ throw new WebApplicationException(Status.NOT_FOUND);
+ }
+ return BugzillaManager.getBugHistoryById(request, bug, productIdString, bugIdString, dayAfter);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new WebApplicationException(e);
+ }
+ }
+
+ /**
+ * Create a new bug from a BugzillaChangeRequest
+ *
+ * @param httpServletRequest
+ * @param changeRequest
+ * @param productIdString
+ * @return id of the new Bug
+ * @throws IOException
+ * @throws ServletException
+ */
+ public static String createBug(HttpServletRequest httpServletRequest,
+ final BugzillaChangeRequest changeRequest,
+ final String productIdString) throws IOException, ServletException {
+ String newBugId = null;
+ try {
+
+ final int productId = Integer.parseInt(productIdString);
+
+ final BugzillaConnector bc = BugzillaManager
+ .getBugzillaConnector(httpServletRequest);
+
+ GetProduct getProducts = new GetProduct(productId);
+ bc.executeMethod(getProducts);
+
+ final Product product = getProducts.getProduct();
+
+ String summary = changeRequest.getTitle();
+ String component = changeRequest.getComponent();
+ String version = changeRequest.getVersion();
+ String operatingSystem = changeRequest.getOperatingSystem();
+ String platform = changeRequest.getPlatform();
+ String description = changeRequest.getDescription();
+
+ BugFactory factory = new BugFactory().newBug().setProduct(
+ product.getName());
+ if (summary != null) {
+ factory.setSummary(summary);
+ }
+ if (version != null) {
+ factory.setVersion(version);
+ }
+ if (component != null) {
+ factory.setComponent(component);
+ }
+ if (platform != null) {
+ factory.setPlatform(platform);
+ } else
+ factory.setPlatform("Other");
+
+ if (operatingSystem != null) {
+ factory.setOperatingSystem(operatingSystem);
+ } else
+ factory.setOperatingSystem("Other");
+
+ if (description != null) {
+ factory.setDescription(description);
+ }
+
+ Bug bug = factory.createBug();
+ ReportBug reportBug = new ReportBug(bug);
+ bc.executeMethod(reportBug);
+ newBugId = Integer.toString(reportBug.getID());
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new WebApplicationException(e);
+ }
+ return newBugId;
+ }
+
+
+
+ public static Product getProduct(final HttpServletRequest httpServletRequest, final String productIdString)
+ {
+ int productId = Integer.parseInt(productIdString);
+ Product product = null;
+
+ try {
+ final BugzillaConnector bc = BugzillaManager.getBugzillaConnector(httpServletRequest);
+ GetProduct getProducts = new GetProduct(productId);
+ bc.executeMethod(getProducts);
+ product = getProducts.getProduct();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new WebApplicationException(e);
+ }
+ return product;
+ }
+
+ /**
+ * Add OSLC links to the comment field of a Bug
+ *
+ * @param request
+ * @param cr - BugzillaChangeRequest containing the links
+ * @throws ServletException
+ * @throws IOException
+ */
+ public static void updateBug(final HttpServletRequest request, final BugzillaChangeRequest cr) throws ServletException, IOException
+ {
+ try
+ {
+ final BugzillaConnector bc = BugzillaManager.getBugzillaConnector(request);
+
+ // No built in field to hold external links. Just add the new link as a comment for now.
+ String comment = getLinksComment(cr);
+ if (comment.length() != 0) {
+ CommentBug bugzillaMethod = new CommentBug(Integer.parseInt(cr.getIdentifier()), comment);
+ bc.executeMethod(bugzillaMethod);
+ }
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ throw new WebApplicationException(e);
+ }
+ }
+
+ protected static void addLinkComment(final StringBuffer buffer, final String linkType, final Link [] links) {
+ if (links != null && (links.length !=0)) {
+ buffer.append(linkType);
+ buffer.append(":\n\n");
+ for (Link link : links) {
+ buffer.append(link.getValue().toString());
+ buffer.append("\n");
+ }
+ }
+ }
+
+ protected static String getLinksComment(final BugzillaChangeRequest cr) {
+ final StringBuffer b = new StringBuffer();
+
+ addLinkComment(b, "Affected by Defect", cr.getAffectedByDefects());
+ addLinkComment(b, "Affects Plan Item", cr.getAffectsPlanItems());
+ addLinkComment(b, "Affects Requirement", cr.getAffectsRequirements());
+ addLinkComment(b, "Affects Test Result", cr.getAffectsTestResults());
+ addLinkComment(b, "Blocks Test Execution Record", cr.getBlocksTestExecutionRecords());
+ addLinkComment(b, "Implements Requirement", cr.getImplementsRequirements());
+ addLinkComment(b, "Related Change Request", cr.getRelatedChangeRequests());
+ addLinkComment(b, "Related Test Execution Record", cr.getRelatedTestExecutionRecords());
+ addLinkComment(b, "Related Test Plane", cr.getRelatedTestPlans());
+ addLinkComment(b, "Related Test Script", cr.getRelatedTestScripts());
+ addLinkComment(b, "Tested by Test Case", cr.getTestedByTestCases());
+ addLinkComment(b, "Tracks Change Set", cr.getTracksChangeSets());
+ addLinkComment(b, "Tracks Requirement", cr.getTracksRequirements());
+
+ return b.toString();
+ }
+
+ static final Map<String, Object> toplevelQueryProperties =
+ new HashMap<String, Object>();
+
+ static {
+
+ toplevelQueryProperties.put(OslcConstants.DCTERMS_NAMESPACE + "identifier",
+ "bug_id");
+ toplevelQueryProperties.put(OslcConstants.DCTERMS_NAMESPACE + "title",
+ "short_desc");
+ toplevelQueryProperties.put(Constants.CHANGE_MANAGEMENT_NAMESPACE + "status",
+ "bug_status");
+
+ Map<String, Object> nestedQueryProperties =
+ new HashMap<String, Object>(1);
+
+ nestedQueryProperties.put(Constants.FOAF_NAMESPACE + "mbox",
+ "assigned_to");
+
+ toplevelQueryProperties.put(OslcConstants.DCTERMS_NAMESPACE + "contributor",
+ nestedQueryProperties);
+
+ toplevelQueryProperties.put(OslcConstants.DCTERMS_NAMESPACE + "created",
+ "creation_ts");
+ toplevelQueryProperties.put(OslcConstants.DCTERMS_NAMESPACE + "modified",
+ "delta_ts");
+ toplevelQueryProperties.put(Constants.BUGZILLA_NAMESPACE + "component",
+ "component");
+ toplevelQueryProperties.put(Constants.BUGZILLA_NAMESPACE + "version",
+ "version");
+ toplevelQueryProperties.put(Constants.BUGZILLA_NAMESPACE + "priority",
+ "priority");
+ toplevelQueryProperties.put(Constants.BUGZILLA_NAMESPACE + "platform",
+ "rep_platform");
+ toplevelQueryProperties.put(Constants.BUGZILLA_NAMESPACE + "operatingSystem",
+ "op_sys");
+ }
+
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/Constants.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/Constants.java
new file mode 100644
index 0000000..a8c8096
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/Constants.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Russell Boykin - initial API and implementation
+ * Alberto Giammaria - initial API and implementation
+ * Chris Peters - initial API and implementation
+ * Gianluca Bernardini - initial API and implementation
+ * Michael Fiedler - Bugzilla adpater implementations
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla;
+
+import org.eclipse.lyo.oslc4j.core.model.OslcConstants;
+
+public interface Constants
+{
+ public static String CHANGE_MANAGEMENT_DOMAIN = "http://open-services.net/ns/cm#";
+ public static String CHANGE_MANAGEMENT_NAMESPACE = "http://open-services.net/ns/cm#";
+ public static String CHANGE_MANAGEMENT_NAMESPACE_PREFIX = "oslc_cm";
+ public static String FOAF_NAMESPACE = "http://xmlns.com/foaf/0.1/";
+ public static String FOAF_NAMESPACE_PREFIX = "foaf";
+ public static String QUALITY_MANAGEMENT_NAMESPACE = "http://open-services.net/ns/qm#";
+ public static String QUALITY_MANAGEMENT_PREFIX = "oslc_qm";
+ public static String REQUIREMENTS_MANAGEMENT_NAMESPACE = "http://open-services.net/ns/rm#";
+ public static String REQUIREMENTS_MANAGEMENT_PREFIX = "oslc_rm";
+ public static String SOFTWARE_CONFIGURATION_MANAGEMENT_NAMESPACE = "http://open-services.net/ns/scm#";
+ public static String SOFTWARE_CONFIGURATION_MANAGEMENT_PREFIX = "oslc_scm";
+ public static String BUGZILLA_DOMAIN = "http://www.bugzilla.org/rdf#";
+ public static String BUGZILLA_NAMESPACE = "http://www.bugzilla.org/rdf#";
+ public static String BUGZILLA_NAMESPACE_PREFIX = "bugz";
+
+
+ public static String CHANGE_REQUEST = "ChangeRequest";
+ public static String TYPE_CHANGE_REQUEST = CHANGE_MANAGEMENT_NAMESPACE + "ChangeRequest";
+ public static String TYPE_CHANGE_SET = SOFTWARE_CONFIGURATION_MANAGEMENT_NAMESPACE + "ChangeSet";
+ public static String TYPE_DISCUSSION = OslcConstants.OSLC_CORE_NAMESPACE + "Discussion";
+ public static String TYPE_PERSON = FOAF_NAMESPACE + "Person";
+ public static String TYPE_REQUIREMENT = REQUIREMENTS_MANAGEMENT_NAMESPACE + "Requirement";
+ public static String TYPE_TEST_CASE = QUALITY_MANAGEMENT_NAMESPACE + "TestCase";
+ public static String TYPE_TEST_EXECUTION_RECORD = QUALITY_MANAGEMENT_NAMESPACE + "TestExecutionRecord";
+ public static String TYPE_TEST_PLAN = QUALITY_MANAGEMENT_NAMESPACE + "TestPlan";
+ public static String TYPE_TEST_RESULT = QUALITY_MANAGEMENT_NAMESPACE + "TestResult";
+ public static String TYPE_TEST_SCRIPT = QUALITY_MANAGEMENT_NAMESPACE + "TestScript";
+
+ public static String PATH_CHANGE_REQUEST = "changeRequest";
+
+ public static String USAGE_LIST = CHANGE_MANAGEMENT_NAMESPACE + "list";
+
+ public static final String HDR_OSLC_VERSION = "OSLC-Core-Version";
+
+ public static final String NEXT_PAGE = "org.eclipse.lyo.oslc4j.bugzilla.NextPage";
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/Credentials.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/Credentials.java
new file mode 100644
index 0000000..94401b7
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/Credentials.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla;
+
+/**
+ * Encapsulates a Bugzilla username and password.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public class Credentials {
+ private String username;
+ private String password;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/exception/BugzillaOAuthException.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/exception/BugzillaOAuthException.java
new file mode 100644
index 0000000..7736585
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/exception/BugzillaOAuthException.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.exception;
+
+import net.oauth.OAuthException;
+
+/**
+ * A special unauthorized exception indicating an OAuth problem.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public class BugzillaOAuthException extends UnauthorizedException {
+ public BugzillaOAuthException(OAuthException e) {
+ super(e);
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/exception/RestException.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/exception/RestException.java
new file mode 100644
index 0000000..79b4c9f
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/exception/RestException.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.exception;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Holds a status code and error message for an error response.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public class RestException extends Exception {
+ private int statusCode;
+ private String message;
+
+ public RestException(int statusCode, String message) {
+ this.statusCode = statusCode;
+ this.message = message;
+ }
+
+ public RestException(Throwable t) {
+ this(t, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+
+ public RestException(Throwable t, int statusCode) {
+ super(t);
+ this.message = t.getMessage();
+ this.statusCode = statusCode;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/exception/UnauthorizedException.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/exception/UnauthorizedException.java
new file mode 100644
index 0000000..b514f36
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/exception/UnauthorizedException.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.exception;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Corresponds to an HTTP 401 response.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public class UnauthorizedException extends RestException {
+ public UnauthorizedException() {
+ super(HttpServletResponse.SC_UNAUTHORIZED,
+ "You must authenticate with Bugzilla for this request.");
+ }
+
+ public UnauthorizedException(String message) {
+ super(HttpServletResponse.SC_UNAUTHORIZED, message);
+ }
+
+ public UnauthorizedException(Throwable t) {
+ super(t, HttpServletResponse.SC_UNAUTHORIZED);
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/jbugzx/rpc/GetAccessibleProducts.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/jbugzx/rpc/GetAccessibleProducts.java
new file mode 100644
index 0000000..af2ce40
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/jbugzx/rpc/GetAccessibleProducts.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.jbugzx.rpc;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.j2bugzilla.base.BugzillaMethod;
+
+public class GetAccessibleProducts implements BugzillaMethod {
+
+ /**
+ * The method Bugzilla will execute via XML-RPC
+ */
+ private static final String METHOD_NAME = "Product.get_accessible_products";
+
+ private Map<Object, Object> params = new HashMap<Object, Object>();
+ private Map<Object, Object> hash = new HashMap<Object, Object>();
+
+ public GetAccessibleProducts() {}
+
+ public Integer[] getIds() {
+ if (hash.containsKey("ids")) {
+ Object[] ids = (Object[])hash.get("ids");
+ Integer[] ints = new Integer[ids.length];
+ System.arraycopy(ids, 0, ints, 0, ids.length);
+ return ints;
+ } else {
+ return new Integer[0];
+ }
+ }
+
+ @Override
+ public void setResultMap(Map<Object, Object> hash) {
+ this.hash = hash;
+ }
+
+ @Override
+ public Map<Object, Object> getParameterMap() {
+ return params;
+ }
+
+ @Override
+ public String getMethodName() {
+ return METHOD_NAME;
+ }
+
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/jbugzx/rpc/GetLegalValues.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/jbugzx/rpc/GetLegalValues.java
new file mode 100644
index 0000000..ba4b436
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/jbugzx/rpc/GetLegalValues.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.jbugzx.rpc;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.j2bugzilla.base.BugzillaMethod;
+
+public class GetLegalValues implements BugzillaMethod {
+
+ /**
+ * The method Bugzilla will execute via XML-RPC
+ */
+ private static final String METHOD_NAME = "Bug.legal_values";
+
+ private Map<Object, Object> params = new HashMap<Object, Object>();
+ private Map<Object, Object> hash = new HashMap<Object, Object>();
+
+ public GetLegalValues(String field, int productId) {
+ params.put("field", field);
+ if (productId != -1) params.put("product_id", productId);
+ }
+
+ public String[] getValues() {
+ if (hash.containsKey("values")) {
+ Object[] values = (Object[])hash.get("values");
+ String[] strings = new String[values.length];
+ System.arraycopy(values, 0, strings, 0, values.length);
+ return strings;
+ } else {
+ return new String[0];
+ }
+ }
+
+ @Override
+ public void setResultMap(Map<Object, Object> hash) {
+ this.hash = hash;
+ }
+
+ @Override
+ public Map<Object, Object> getParameterMap() {
+ return params;
+ }
+
+ @Override
+ public String getMethodName() {
+ return METHOD_NAME;
+ }
+
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/BugzillaChangeRequest.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/BugzillaChangeRequest.java
new file mode 100644
index 0000000..944d5db
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/BugzillaChangeRequest.java
@@ -0,0 +1,285 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Sam Padgett - initial API and implementation
+ * Michael Fiedler - adapted for OSLC4J
+ *
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.resources;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.lyo.oslc4j.bugzilla.BugzillaManager;
+import org.eclipse.lyo.oslc4j.bugzilla.Constants;
+import org.eclipse.lyo.oslc4j.bugzilla.jbugzx.rpc.GetAccessibleProducts;
+import org.eclipse.lyo.oslc4j.bugzilla.trs.GetProduct;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcDescription;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcName;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcNamespace;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcOccurs;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcPropertyDefinition;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcReadOnly;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcResourceShape;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcTitle;
+import org.eclipse.lyo.oslc4j.core.model.Link;
+import org.eclipse.lyo.oslc4j.core.model.Occurs;
+
+import com.j2bugzilla.base.Bug;
+import com.j2bugzilla.base.BugFactory;
+import com.j2bugzilla.base.BugzillaConnector;
+import com.j2bugzilla.base.BugzillaException;
+import com.j2bugzilla.base.ConnectionException;
+
+//OSLC4J should give an rdf:type of oslc_cm:ChangeRequest
+@OslcNamespace(Constants.CHANGE_MANAGEMENT_NAMESPACE)
+@OslcName(Constants.CHANGE_REQUEST)
+@OslcResourceShape(title = "Change Request Resource Shape", describes = Constants.TYPE_CHANGE_REQUEST)
+public final class BugzillaChangeRequest
+ extends ChangeRequest
+{
+ public BugzillaChangeRequest() throws URISyntaxException {
+ super();
+
+ }
+ public BugzillaChangeRequest(URI about) throws URISyntaxException {
+ super(about);
+
+ }
+
+ //Bugzilla extended attributes beyond OSLC base ChangeRequest
+ private String product = null;
+ private String component = null;
+ private String version = null;
+ private String priority = null;
+ private String platform = null;
+ private String operatingSystem = null;
+
+
+ @OslcDescription("The Bugzilla product definition for this change request.")
+ @OslcOccurs(Occurs.ZeroOrOne)
+ @OslcPropertyDefinition(Constants.BUGZILLA_NAMESPACE + "component")
+ @OslcTitle("Component")
+ public String getComponent() {
+ return component;
+ }
+
+ public void setComponent(String component) {
+ this.component = component;
+ }
+
+ @OslcDescription("The Bugzilla version for this change request.")
+ @OslcOccurs(Occurs.ZeroOrOne)
+ @OslcReadOnly
+ @OslcPropertyDefinition(Constants.BUGZILLA_NAMESPACE + "version")
+ @OslcTitle("Version")
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ @OslcDescription("The Bugzilla priority for this change request.")
+ @OslcOccurs(Occurs.ZeroOrOne)
+ @OslcPropertyDefinition(Constants.BUGZILLA_NAMESPACE + "priority")
+ @OslcTitle("Priority")
+ public String getPriority() {
+ return priority;
+ }
+
+ public void setPriority(String priority) {
+ this.priority = priority;
+ }
+
+ @OslcDescription("The Bugzilla platform for this change request.")
+ @OslcOccurs(Occurs.ZeroOrOne)
+ @OslcPropertyDefinition(Constants.BUGZILLA_NAMESPACE + "platform")
+ @OslcTitle("Platform")
+ public String getPlatform() {
+ return platform;
+ }
+
+ public void setPlatform(String platform) {
+ this.platform = platform;
+ }
+
+ @OslcDescription("The Bugzilla operating system for this change request.")
+ @OslcOccurs(Occurs.ZeroOrOne)
+ @OslcPropertyDefinition(Constants.BUGZILLA_NAMESPACE + "operatingSystem")
+ @OslcTitle("Operating System")
+ public String getOperatingSystem() {
+ return operatingSystem;
+ }
+
+ public void setOperatingSystem(String operatingSystem) {
+ this.operatingSystem = operatingSystem;
+ }
+
+
+ /**
+ * Converts a {@link Bug} to an OSLC-CM BugzillaChangeRequest.
+ *
+ * @param bug
+ * the bug
+ * @return the ChangeRequest to be serialized
+ * @throws URISyntaxException
+ * on errors setting the bug URI
+ * @throws ServletException
+ * @throws IOException
+ */
+ public static BugzillaChangeRequest fromBug(Bug bug, HttpServletRequest httpServletRequest)
+ throws URISyntaxException, IOException, ServletException {
+ BugzillaChangeRequest changeRequest = new BugzillaChangeRequest();
+ changeRequest.setIdentifier(bug.getID());
+ changeRequest.setTitle(bug.getSummary());
+ changeRequest.setStatus(bug.getStatus());
+
+ //Map contributor to the person this bug is assigned to
+ Object assignedTo = bug.getParameterMap().get("assigned_to");
+ if (assignedTo != null) {
+ String email = assignedTo.toString();
+ Person contributor = new Person();
+ contributor.setUri(new URI(BugzillaManager.getServletBase() + "/person?mbox=" + URLEncoder.encode(email, "UTF-8")));
+ contributor.setMbox(email);
+ contributor.setAbout(contributor.getUri());
+ ArrayList<Person> contributors = new ArrayList<Person>();
+ contributors.add(contributor);
+ changeRequest.setContributors(contributors);
+ }
+
+ Date createdDate = (Date) bug.getParameterMap().get("creation_time");
+ changeRequest.setCreated(createdDate);
+
+ Date modifiedDate = (Date) bug.getParameterMap().get("last_change_time");
+ changeRequest.setModified(modifiedDate);
+
+ changeRequest.setProduct(bug.getProduct());
+ changeRequest.setComponent(bug.getComponent());
+
+ // Work around a bug in j2bugzilla. Bug.getVersion() results in a class cast exception.
+ Object version = bug.getParameterMap().get("version");
+ if (version != null) {
+ changeRequest.setVersion(version.toString());
+ }
+
+ changeRequest.setPriority(bug.getPriority());
+
+ Map<?, ?> internals = bug.getParameterMap();
+ changeRequest.setPlatform((String) internals.get("platform"));
+ changeRequest.setOperatingSystem((String) internals.get("op_sys"));
+
+ /* "see also" support */
+ Object[] seealsos = (Object[]) bug.getParameterMap().get("see_also"); //$NON-NLS-1$
+ if ((seealsos != null) && (seealsos.length > 0)) {
+ for(Object o : seealsos) {
+ String uri = (String)o;
+ String cgiuri = BugzillaManager.getBugzillaUri();
+ if (cgiuri.endsWith("/")) {
+ cgiuri += "show_bug.cgi?id=";
+ } else {
+ cgiuri += "/show_bug.cgi?id=";
+ }
+ if (uri.startsWith(cgiuri)) {
+ // Bugid
+ String bugId = uri.substring(cgiuri.length());
+ Bug relatedBug = BugzillaManager.getBugById(httpServletRequest, bugId);
+ String productName = relatedBug.getProduct();
+ BugzillaConnector bc = BugzillaManager.getBugzillaConnector(httpServletRequest);
+ if (bc != null) {
+ // get products
+ GetAccessibleProducts getProductIds = new GetAccessibleProducts();
+ try {
+ bc.executeMethod(getProductIds);
+ } catch (BugzillaException e) {
+ e.printStackTrace();
+ throw new WebApplicationException(e, Status.INTERNAL_SERVER_ERROR);
+ }
+ Integer[] ids = getProductIds.getIds();
+ GetProduct getProduct= new GetProduct(ids);
+ try {
+ bc.executeMethod(getProduct);
+ } catch (BugzillaException e) {
+ e.printStackTrace();
+ throw new WebApplicationException(e, Status.INTERNAL_SERVER_ERROR);
+ }
+ String productId = getProduct.getProductID(productName);
+ URI oslcUri = new URI(BugzillaManager.getBugzServiceBase() + "/" + productId + "/changeRequests/" + bugId);
+ changeRequest.addRelatedChangeRequest(new Link(oslcUri));
+ }
+ }
+ }
+ }
+ return changeRequest;
+ }
+
+ /**
+ * Creates a {@link Bug} from an OSLC-CM ChangeRequest.
+ *
+ * @param bug the bug
+ * @return the ChangeRequest to be serialized
+ * @throws BugzillaException
+ * @throws ConnectionException
+ * @throws InvalidDescriptionException
+ * @throws URISyntaxException on errors setting the bug URI
+ */
+ public Bug toBug() throws ConnectionException, BugzillaException {
+ BugFactory factory = new BugFactory().newBug();
+ if (product != null) {
+ factory.setProduct(product);
+ }
+ if (this.getTitle() != null) {
+ factory.setSummary(this.getTitle());
+ }
+ if (this.getDescription() != null) {
+ factory.setDescription(this.getDescription());
+ }
+ if (version != null) {
+ factory.setVersion(version);
+ }
+ if (component != null) {
+ factory.setComponent(component);
+ }
+ if (platform != null) {
+ factory.setPlatform(platform);
+ }
+ if (operatingSystem != null) {
+ factory.setOperatingSystem(operatingSystem);
+ }
+
+ return factory.createBug();
+ }
+
+ public void setIdentifier(int identifier) throws URISyntaxException {
+ setIdentifier(Integer.toString(identifier));
+ }
+
+ public String getProduct() {
+ return product;
+ }
+
+ public void setProduct(String product) {
+ this.product = product;
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/ChangeRequest.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/ChangeRequest.java
new file mode 100644
index 0000000..66b9e27
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/ChangeRequest.java
@@ -0,0 +1,890 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Russell Boykin - initial API and implementation
+ * Alberto Giammaria - initial API and implementation
+ * Chris Peters - initial API and implementation
+ * Gianluca Bernardini - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.resources;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.lyo.oslc4j.bugzilla.Constants;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcAllowedValue;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcDescription;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcName;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcOccurs;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcPropertyDefinition;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcRange;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcReadOnly;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcRepresentation;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcTitle;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcValueType;
+import org.eclipse.lyo.oslc4j.core.model.AbstractResource;
+import org.eclipse.lyo.oslc4j.core.model.Link;
+import org.eclipse.lyo.oslc4j.core.model.Occurs;
+import org.eclipse.lyo.oslc4j.core.model.OslcConstants;
+import org.eclipse.lyo.oslc4j.core.model.Representation;
+import org.eclipse.lyo.oslc4j.core.model.ValueType;
+
+public class ChangeRequest
+ extends AbstractResource
+{
+ private final Set<Link> affectedByDefects = new HashSet<Link>();
+ private final Set<Link> affectsPlanItems = new HashSet<Link>();
+ private final Set<Link> affectsRequirements = new HashSet<Link>();
+ private final Set<Link> affectsTestResults = new HashSet<Link>();
+ private final Set<Link> blocksTestExecutionRecords = new HashSet<Link>();
+ private final List<Person> contributors = new ArrayList<Person>();
+ private final List<Person> creators = new ArrayList<Person>();
+ private final Set<Type> dctermsTypes = new TreeSet<Type>();
+ private final Set<Link> implementsRequirements = new HashSet<Link>();
+ private final Set<Link> relatedChangeRequests = new HashSet<Link>();
+ private final Set<Link> relatedResources = new HashSet<Link>(); // TODO - Extension to point to any other OSLC resource(s).
+ private final Set<Link> relatedTestCases = new HashSet<Link>();
+ private final Set<Link> relatedTestExecutionRecords = new HashSet<Link>();
+ private final Set<Link> relatedTestPlans = new HashSet<Link>();
+ private final Set<Link> relatedTestScripts = new HashSet<Link>();
+ private final Set<String> subjects = new TreeSet<String>();
+ private final Set<Link> testedByTestCases = new HashSet<Link>();
+ private final Set<Link> tracksChangeSets = new HashSet<Link>();
+ private final Set<Link> tracksRequirements = new HashSet<Link>();
+ private final Set<URI> rdfTypes = new TreeSet<URI>();
+
+ private Boolean approved;
+ private Boolean closed;
+ private Date closeDate;
+ private Date created;
+ private String description;
+ private URI discussedBy;
+ private Boolean fixed;
+ private String identifier;
+ private Boolean inProgress;
+ private URI instanceShape;
+ private Date modified;
+ private Boolean reviewed;
+ private URI serviceProvider;
+ private Severity severity = Severity.Unclassified; // TODO - Added severity for demo
+ private String shortTitle;
+ private String status;
+ private String title;
+ private Boolean verified;
+
+ public ChangeRequest()
+ throws URISyntaxException
+ {
+ super();
+
+ rdfTypes.add(new URI(Constants.TYPE_CHANGE_REQUEST));
+ }
+
+ public ChangeRequest(final URI about)
+ throws URISyntaxException
+ {
+ super(about);
+
+ rdfTypes.add(new URI(Constants.TYPE_CHANGE_REQUEST));
+ }
+
+ public void addAffectedByDefect(final Link affectedByDefect)
+ {
+ this.affectedByDefects.add(affectedByDefect);
+ }
+
+ public void addAffectsPlanItem(final Link affectsPlanItem)
+ {
+ this.affectsPlanItems.add(affectsPlanItem);
+ }
+
+ public void addAffectsRequirement(final Link affectsRequirement)
+ {
+ this.affectsRequirements.add(affectsRequirement);
+ }
+
+ public void addAffectsTestResult(final Link affectsTestResult)
+ {
+ this.affectsTestResults.add(affectsTestResult);
+ }
+
+ public void addBlocksTestExecutionRecord(final Link blocksTestExecutionRecord)
+ {
+ this.blocksTestExecutionRecords.add(blocksTestExecutionRecord);
+ }
+
+ public void addContributor(final Person contributor)
+ {
+ this.contributors.add(contributor);
+ }
+
+ public void addCreator(final Person creator)
+ {
+ this.creators.add(creator);
+ }
+
+ public void addDctermsType(final String dctermsType)
+ {
+ this.dctermsTypes.add(Type.fromString(dctermsType));
+ }
+
+ public void addImplementsRequirement(final Link implementsRequirement)
+ {
+ this.implementsRequirements.add(implementsRequirement);
+ }
+
+ public void addRdfType(final URI rdfType)
+ {
+ this.rdfTypes.add(rdfType);
+ }
+
+ public void addRelatedChangeRequest(final Link relatedChangeRequest)
+ {
+ this.relatedChangeRequests.add(relatedChangeRequest);
+ }
+
+ public void addRelatedResource(final Link relatedResource)
+ {
+ this.relatedResources.add(relatedResource);
+ }
+
+ public void addRelatedTestCase(final Link relatedTestCase)
+ {
+ this.relatedTestCases.add(relatedTestCase);
+ }
+
+ public void addRelatedTestExecutionRecord(final Link relatedTestExecutionRecord)
+ {
+ this.relatedTestExecutionRecords.add(relatedTestExecutionRecord);
+ }
+
+ public void addRelatedTestPlan(final Link relatedTestPlan)
+ {
+ this.relatedTestPlans.add(relatedTestPlan);
+ }
+
+ public void addRelatedTestScript(final Link relatedTestScript)
+ {
+ this.relatedTestScripts.add(relatedTestScript);
+ }
+
+ public void addSubject(final String subject)
+ {
+ this.subjects.add(subject);
+ }
+
+ public void addTestedByTestCase(final Link testedByTestCase)
+ {
+ this.testedByTestCases.add(testedByTestCase);
+ }
+
+ public void addTracksChangeSet(final Link tracksChangeSet)
+ {
+ this.tracksChangeSets.add(tracksChangeSet);
+ }
+
+ public void addTracksRequirement(final Link tracksRequirement)
+ {
+ this.tracksRequirements.add(tracksRequirement);
+ }
+
+ @OslcDescription("Change request is affected by a reported defect.")
+ @OslcName("affectedByDefect")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "affectedByDefect")
+ @OslcRange(Constants.TYPE_CHANGE_REQUEST)
+ @OslcReadOnly(false)
+ @OslcTitle("Affected By Defects")
+ public Link[] getAffectedByDefects()
+ {
+ return affectedByDefects.toArray(new Link[affectedByDefects.size()]);
+ }
+
+ @OslcDescription("Change request affects a plan item. ")
+ @OslcName("affectsPlanItem")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "affectsPlanItem")
+ @OslcRange(Constants.TYPE_CHANGE_REQUEST)
+ @OslcReadOnly(false)
+ @OslcTitle("Affects Plan Items")
+ public Link[] getAffectsPlanItems()
+ {
+ return affectsPlanItems.toArray(new Link[affectsPlanItems.size()]);
+ }
+
+ @OslcDescription("Change request affecting a Requirement.")
+ @OslcName("affectsRequirement")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "affectsRequirement")
+ @OslcRange(Constants.TYPE_REQUIREMENT)
+ @OslcReadOnly(false)
+ @OslcTitle("Affects Requirements")
+ public Link[] getAffectsRequirements()
+ {
+ return affectsRequirements.toArray(new Link[affectsRequirements.size()]);
+ }
+
+ @OslcDescription("Associated QM resource that is affected by this Change Request.")
+ @OslcName("affectsTestResult")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "affectsTestResult")
+ @OslcRange(Constants.TYPE_TEST_RESULT)
+ @OslcReadOnly(false)
+ @OslcTitle("Affects Test Results")
+ public Link[] getAffectsTestResults()
+ {
+ return affectsTestResults.toArray(new Link[affectsTestResults.size()]);
+ }
+
+ @OslcDescription("Associated QM resource that is blocked by this Change Request.")
+ @OslcName("blocksTestExecutionRecord")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "blocksTestExecutionRecord")
+ @OslcRange(Constants.TYPE_TEST_EXECUTION_RECORD)
+ @OslcReadOnly(false)
+ @OslcTitle("Blocks Test Execution Records")
+ public Link[] getBlocksTestExecutionRecords()
+ {
+ return blocksTestExecutionRecords.toArray(new Link[blocksTestExecutionRecords.size()]);
+ }
+
+ @OslcDescription("The date at which no further activity or work is intended to be conducted. ")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "closeDate")
+ @OslcReadOnly
+ @OslcTitle("Close Date")
+ public Date getCloseDate()
+ {
+ return closeDate;
+ }
+
+ @OslcDescription("The person(s) who are responsible for the work needed to complete the change request.")
+ @OslcName("contributor")
+ @OslcPropertyDefinition(OslcConstants.DCTERMS_NAMESPACE + "contributor")
+ @OslcRepresentation(Representation.Inline)
+ @OslcValueType(ValueType.LocalResource)
+ @OslcRange(Constants.TYPE_PERSON)
+ @OslcTitle("Contributors")
+ public List<Person> getContributors()
+ {
+ return contributors;
+ }
+
+ @OslcDescription("Timestamp of resource creation.")
+ @OslcPropertyDefinition(OslcConstants.DCTERMS_NAMESPACE + "created")
+ @OslcReadOnly
+ @OslcTitle("Created")
+ public Date getCreated()
+ {
+ return created;
+ }
+
+ @OslcDescription("Creator or creators of resource.")
+ @OslcName("creator")
+ @OslcPropertyDefinition(OslcConstants.DCTERMS_NAMESPACE + "creator")
+ @OslcRepresentation(Representation.Inline)
+ @OslcValueType(ValueType.LocalResource)
+ @OslcRange(Constants.TYPE_PERSON)
+ @OslcTitle("Creators")
+ public List<Person> getCreators()
+ {
+ return creators;
+ }
+
+ @OslcAllowedValue({"Defect", "Task", "Story", "Bug Report", "Feature Request"})
+ @OslcDescription("A short string representation for the type, example 'Defect'.")
+ @OslcName("type")
+ @OslcPropertyDefinition(OslcConstants.DCTERMS_NAMESPACE + "type")
+ @OslcTitle("Types")
+ public String[] getDctermsTypes()
+ {
+ final String[] result = new String[dctermsTypes.size()];
+
+ int index = 0;
+
+ for (final Type type : dctermsTypes)
+ {
+ result[index++] = type.toString();
+ }
+
+ return result;
+ }
+
+ @OslcDescription("Descriptive text (reference: Dublin Core) about resource represented as rich text in XHTML content.")
+ @OslcPropertyDefinition(OslcConstants.DCTERMS_NAMESPACE + "description")
+ @OslcTitle("Description")
+ @OslcValueType(ValueType.XMLLiteral)
+ public String getDescription()
+ {
+ return description;
+ }
+
+ @OslcDescription("A series of notes and comments about this change request.")
+ @OslcPropertyDefinition(OslcConstants.OSLC_CORE_NAMESPACE + "discussedBy")
+ @OslcRange(Constants.TYPE_DISCUSSION)
+ @OslcTitle("Discussed By")
+ public URI getDiscussedBy()
+ {
+ return discussedBy;
+ }
+
+ @OslcDescription("A unique identifier for a resource. Assigned by the service provider when a resource is created. Not intended for end-user display.")
+ @OslcOccurs(Occurs.ExactlyOne)
+ @OslcPropertyDefinition(OslcConstants.DCTERMS_NAMESPACE + "identifier")
+ @OslcReadOnly
+ @OslcTitle("Identifier")
+ public String getIdentifier()
+ {
+ return identifier;
+ }
+
+ @OslcDescription("Implements associated Requirement.")
+ @OslcName("implementsRequirement")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "implementsRequirement")
+ @OslcRange(Constants.TYPE_REQUIREMENT)
+ @OslcReadOnly(false)
+ @OslcTitle("Implements Requirements")
+ public Link[] getImplementsRequirements()
+ {
+ return implementsRequirements.toArray(new Link[implementsRequirements.size()]);
+ }
+
+ @OslcDescription("Resource Shape that provides hints as to resource property value-types and allowed values. ")
+ @OslcPropertyDefinition(OslcConstants.OSLC_CORE_NAMESPACE + "instanceShape")
+ @OslcRange(OslcConstants.TYPE_RESOURCE_SHAPE)
+ @OslcTitle("Instance Shape")
+ public URI getInstanceShape()
+ {
+ return instanceShape;
+ }
+
+ @OslcDescription("Timestamp last latest resource modification.")
+ @OslcPropertyDefinition(OslcConstants.DCTERMS_NAMESPACE + "modified")
+ @OslcReadOnly
+ @OslcTitle("Modified")
+ public Date getModified()
+ {
+ return modified;
+ }
+
+ @OslcDescription("The resource type URIs.")
+ @OslcName("type")
+ @OslcPropertyDefinition(OslcConstants.RDF_NAMESPACE + "type")
+ @OslcTitle("Types")
+ public URI[] getRdfTypes()
+ {
+ return rdfTypes.toArray(new URI[rdfTypes.size()]);
+ }
+
+ @OslcDescription("This relationship is loosely coupled and has no specific meaning.")
+ @OslcName("relatedChangeRequest")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "relatedChangeRequest")
+ @OslcRange(Constants.TYPE_CHANGE_REQUEST)
+ @OslcReadOnly(false)
+ @OslcTitle("Related Change Requests")
+ public Link[] getRelatedChangeRequests()
+ {
+ return relatedChangeRequests.toArray(new Link[relatedChangeRequests.size()]);
+ }
+
+ @OslcDescription("Related OSLC resources of any type.")
+ @OslcName("relatedResource")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "relatedResource")
+ @OslcTitle("Related Resources")
+ public Link[] getRelatedResources()
+ {
+ return relatedResources.toArray(new Link[relatedResources.size()]);
+ }
+
+ @OslcDescription("Related QM test case resource.")
+ @OslcName("relatedTestCase")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "relatedTestCase")
+ @OslcRange(Constants.TYPE_TEST_CASE)
+ @OslcReadOnly(false)
+ @OslcTitle("Related Test Cases")
+ public Link[] getRelatedTestCases()
+ {
+ return relatedTestCases.toArray(new Link[relatedTestCases.size()]);
+ }
+
+ @OslcDescription("Related to a QM test execution resource.")
+ @OslcName("relatedTestExecutionRecord")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "relatedTestExecutionRecord")
+ @OslcRange(Constants.TYPE_TEST_EXECUTION_RECORD)
+ @OslcReadOnly(false)
+ @OslcTitle("Related Test Execution Records")
+ public Link[] getRelatedTestExecutionRecords()
+ {
+ return relatedTestExecutionRecords.toArray(new Link[relatedTestExecutionRecords.size()]);
+ }
+
+ @OslcDescription("Related QM test plan resource.")
+ @OslcName("relatedTestPlan")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "relatedTestPlan")
+ @OslcRange(Constants.TYPE_TEST_PLAN)
+ @OslcReadOnly(false)
+ @OslcTitle("Related Test Plans")
+ public Link[] getRelatedTestPlans()
+ {
+ return relatedTestPlans.toArray(new Link[relatedTestPlans.size()]);
+ }
+
+ @OslcDescription("Related QM test script resource.")
+ @OslcName("relatedTestScript")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "relatedTestScript")
+ @OslcRange(Constants.TYPE_TEST_SCRIPT)
+ @OslcReadOnly(false)
+ @OslcTitle("Related Test Scripts")
+ public Link[] getRelatedTestScripts()
+ {
+ return relatedTestScripts.toArray(new Link[relatedTestScripts.size()]);
+ }
+
+ @OslcDescription("The scope of a resource is a URI for the resource's OSLC Service Provider.")
+ @OslcPropertyDefinition(OslcConstants.OSLC_CORE_NAMESPACE + "serviceProvider")
+ @OslcRange(OslcConstants.TYPE_SERVICE_PROVIDER)
+ @OslcTitle("Service Provider")
+ public URI getServiceProvider()
+ {
+ return serviceProvider;
+ }
+
+ @OslcAllowedValue({"Unclassified", "Minor", "Normal", "Major", "Critical", "Blocker"})
+ @OslcDescription("Severity of change request.")
+ @OslcOccurs(Occurs.ExactlyOne)
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "severity")
+ @OslcTitle("Severity")
+ public String getSeverity()
+ {
+ return severity.toString();
+ }
+
+ @OslcDescription("Short name identifying a resource, often used as an abbreviated identifier for presentation to end-users.")
+ @OslcPropertyDefinition(OslcConstants.OSLC_CORE_NAMESPACE + "shortTitle")
+ @OslcTitle("Short Title")
+ @OslcValueType(ValueType.XMLLiteral)
+ public String getShortTitle()
+ {
+ return shortTitle;
+ }
+
+ @OslcDescription("Used to indicate the status of the change request based on values defined by the service provider. Most often a read-only property. Some possible values may include: 'Submitted', 'Done', 'InProgress', etc.")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "status")
+ @OslcTitle("Status")
+ public String getStatus()
+ {
+ return status;
+ }
+
+ @OslcDescription("Tag or keyword for a resource. Each occurrence of a dcterms:subject property denotes an additional tag for the resource.")
+ @OslcName("subject")
+ @OslcPropertyDefinition(OslcConstants.DCTERMS_NAMESPACE + "subject")
+ @OslcReadOnly(false)
+ @OslcTitle("Subjects")
+ public String[] getSubjects()
+ {
+ return subjects.toArray(new String[subjects.size()]);
+ }
+
+ @OslcDescription("Test case by which this change request is tested.")
+ @OslcName("testedByTestCase")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "testedByTestCase")
+ @OslcRange(Constants.TYPE_TEST_CASE)
+ @OslcReadOnly(false)
+ @OslcTitle("Tested by Test Cases")
+ public Link[] getTestedByTestCases()
+ {
+ return testedByTestCases.toArray(new Link[testedByTestCases.size()]);
+ }
+
+ @OslcDescription("Title (reference: Dublin Core) or often a single line summary of the resource represented as rich text in XHTML content.")
+ @OslcOccurs(Occurs.ExactlyOne)
+ @OslcPropertyDefinition(OslcConstants.DCTERMS_NAMESPACE + "title")
+ @OslcTitle("Title")
+ @OslcValueType(ValueType.XMLLiteral)
+ public String getTitle()
+ {
+ return title;
+ }
+
+ @OslcDescription("Tracks SCM change set resource.")
+ @OslcName("tracksChangeSet")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "tracksChangeSet")
+ @OslcRange(Constants.TYPE_CHANGE_SET)
+ @OslcReadOnly(false)
+ @OslcTitle("Tracks Change Sets")
+ public Link[] getTracksChangeSets()
+ {
+ return tracksChangeSets.toArray(new Link[tracksChangeSets.size()]);
+ }
+
+ @OslcDescription("Tracks the associated Requirement or Requirement ChangeSet resources.")
+ @OslcName("tracksRequirement")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "tracksRequirement")
+ @OslcRange(Constants.TYPE_REQUIREMENT)
+ @OslcReadOnly(false)
+ @OslcTitle("Tracks Requirements")
+ public Link[] getTracksRequirements()
+ {
+ return tracksRequirements.toArray(new Link[tracksRequirements.size()]);
+ }
+
+ @OslcDescription("Whether or not the Change Request has been approved.")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "approved")
+ @OslcReadOnly
+ @OslcTitle("Approved")
+ public Boolean isApproved()
+ {
+ return approved;
+ }
+
+ @OslcDescription("Whether or not the Change Request is completely done, no further fixes or fix verification is needed.")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "closed")
+ @OslcReadOnly
+ @OslcTitle("Closed")
+ public Boolean isClosed()
+ {
+ return closed;
+ }
+
+ @OslcDescription("Whether or not the Change Request has been fixed.")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "fixed")
+ @OslcReadOnly
+ @OslcTitle("Fixed")
+ public Boolean isFixed()
+ {
+ return fixed;
+ }
+
+ @OslcDescription("Whether or not the Change Request in a state indicating that active work is occurring. If oslc_cm:inprogress is true, then oslc_cm:fixed and oslc_cm:closed must also be false.")
+ @OslcName("inprogress")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "inprogress")
+ @OslcReadOnly
+ @OslcTitle("In Progress")
+ public Boolean isInProgress()
+ {
+ return inProgress;
+ }
+
+ @OslcDescription("Whether or not the Change Request has been reviewed.")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "reviewed")
+ @OslcReadOnly
+ @OslcTitle("Reviewed")
+ public Boolean isReviewed()
+ {
+ return reviewed;
+ }
+
+ @OslcDescription("Whether or not the resolution or fix of the Change Request has been verified.")
+ @OslcPropertyDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE + "verified")
+ @OslcReadOnly
+ @OslcTitle("Verified")
+ public Boolean isVerified()
+ {
+ return verified;
+ }
+
+ public void setAffectedByDefects(final Link[] affectedByDefects)
+ {
+ this.affectedByDefects.clear();
+
+ if (affectedByDefects != null)
+ {
+ this.affectedByDefects.addAll(Arrays.asList(affectedByDefects));
+ }
+ }
+
+ public void setAffectsPlanItems(final Link[] affectsPlanItems)
+ {
+ this.affectsPlanItems.clear();
+
+ if (affectsPlanItems != null)
+ {
+ this.affectsPlanItems.addAll(Arrays.asList(affectsPlanItems));
+ }
+ }
+
+ public void setAffectsRequirements(final Link[] affectsRequirements)
+ {
+ this.affectsRequirements.clear();
+
+ if (affectsRequirements != null)
+ {
+ this.affectsRequirements.addAll(Arrays.asList(affectsRequirements));
+ }
+ }
+
+ public void setAffectsTestResults(final Link[] affectsTestResults)
+ {
+ this.affectsTestResults.clear();
+
+ if (affectsTestResults != null)
+ {
+ this.affectsTestResults.addAll(Arrays.asList(affectsTestResults));
+ }
+ }
+
+ public void setApproved(final Boolean approved)
+ {
+ this.approved = approved;
+ }
+
+ public void setBlocksTestExecutionRecords(final Link[] blocksTestExecutionRecords)
+ {
+ this.blocksTestExecutionRecords.clear();
+
+ if (blocksTestExecutionRecords != null)
+ {
+ this.blocksTestExecutionRecords.addAll(Arrays.asList(blocksTestExecutionRecords));
+ }
+ }
+
+ public void setClosed(final Boolean closed)
+ {
+ this.closed = closed;
+ }
+
+ public void setCloseDate(final Date closeDate)
+ {
+ this.closeDate = closeDate;
+ }
+
+ public void setContributors(final List<Person> contributors)
+ {
+ this.contributors.clear();
+
+ if (contributors != null)
+ {
+ this.contributors.addAll(contributors);
+ }
+ }
+
+ public void setCreated(final Date created)
+ {
+ this.created = created;
+ }
+
+ public void setCreators(final List<Person> creators)
+ {
+ this.creators.clear();
+
+ if (creators != null)
+ {
+ this.creators.addAll(creators);
+ }
+ }
+
+ public void setDctermsTypes(final String[] dctermsTypes)
+ {
+ this.dctermsTypes.clear();
+
+ if (dctermsTypes != null)
+ {
+ for (final String type : dctermsTypes)
+ {
+ this.dctermsTypes.add(Type.fromString(type));
+ }
+ }
+ }
+
+ public void setDescription(final String description)
+ {
+ this.description = description;
+ }
+
+ public void setDiscussedBy(final URI discussedBy)
+ {
+ this.discussedBy = discussedBy;
+ }
+
+ public void setFixed(final Boolean fixed)
+ {
+ this.fixed = fixed;
+ }
+
+ public void setIdentifier(final String identifier)
+ {
+ this.identifier = identifier;
+ }
+
+ public void setImplementsRequirements(final Link[] implementsRequirements)
+ {
+ this.implementsRequirements.clear();
+
+ if (implementsRequirements != null)
+ {
+ this.implementsRequirements.addAll(Arrays.asList(implementsRequirements));
+ }
+ }
+
+ public void setInProgress(final Boolean inProgress)
+ {
+ this.inProgress = inProgress;
+ }
+
+ public void setInstanceShape(final URI instanceShape)
+ {
+ this.instanceShape = instanceShape;
+ }
+
+ public void setModified(final Date modified)
+ {
+ this.modified = modified;
+ }
+
+ public void setRdfTypes(final URI[] rdfTypes)
+ {
+ this.rdfTypes.clear();
+
+ if (rdfTypes != null)
+ {
+ this.rdfTypes.addAll(Arrays.asList(rdfTypes));
+ }
+ }
+
+ public void setRelatedChangeRequests(final Link[] relatedChangeRequests)
+ {
+ this.relatedChangeRequests.clear();
+
+ if (relatedChangeRequests != null)
+ {
+ this.relatedChangeRequests.addAll(Arrays.asList(relatedChangeRequests));
+ }
+ }
+
+ public void setRelatedResources(final Link[] relatedResources)
+ {
+ this.relatedResources.clear();
+
+ if (relatedResources != null)
+ {
+ this.relatedResources.addAll(Arrays.asList(relatedResources));
+ }
+ }
+
+ public void setRelatedTestCases(final Link[] relatedTestCases)
+ {
+ this.relatedTestCases.clear();
+
+ if (relatedTestCases != null)
+ {
+ this.relatedTestCases.addAll(Arrays.asList(relatedTestCases));
+ }
+ }
+
+ public void setRelatedTestExecutionRecords(final Link[] relatedTestExecutionRecords)
+ {
+ this.relatedTestExecutionRecords.clear();
+
+ if (relatedTestExecutionRecords != null)
+ {
+ this.relatedTestExecutionRecords.addAll(Arrays.asList(relatedTestExecutionRecords));
+ }
+ }
+
+ public void setRelatedTestPlans(final Link[] relatedTestPlans)
+ {
+ this.relatedTestPlans.clear();
+
+ if (relatedTestPlans != null)
+ {
+ this.relatedTestPlans.addAll(Arrays.asList(relatedTestPlans));
+ }
+ }
+
+ public void setRelatedTestScripts(final Link[] relatedTestScripts)
+ {
+ this.relatedTestScripts.clear();
+
+ if (relatedTestScripts != null)
+ {
+ this.relatedTestScripts.addAll(Arrays.asList(relatedTestScripts));
+ }
+ }
+
+ public void setReviewed(final Boolean reviewed)
+ {
+ this.reviewed = reviewed;
+ }
+
+ public void setServiceProvider(final URI serviceProvider)
+ {
+ this.serviceProvider = serviceProvider;
+ }
+
+ public void setSeverity(final String severity)
+ {
+ this.severity = Severity.valueOf(severity);
+ }
+
+ public void setShortTitle(final String shortTitle)
+ {
+ this.shortTitle = shortTitle;
+ }
+
+ public void setStatus(final String status)
+ {
+ this.status = status;
+ }
+
+ public void setSubjects(final String[] subjects)
+ {
+ this.subjects.clear();
+
+ if (subjects != null)
+ {
+ this.subjects.addAll(Arrays.asList(subjects));
+ }
+ }
+
+ public void setTestedByTestCases(final Link[] testedByTestCases)
+ {
+ this.testedByTestCases.clear();
+
+ if (testedByTestCases != null)
+ {
+ this.testedByTestCases.addAll(Arrays.asList(testedByTestCases));
+ }
+ }
+
+ public void setTitle(final String title)
+ {
+ this.title = title;
+ }
+
+ public void setTracksChangeSets(final Link[] tracksChangeSets)
+ {
+ this.tracksChangeSets.clear();
+
+ if (tracksChangeSets != null)
+ {
+ this.tracksChangeSets.addAll(Arrays.asList(tracksChangeSets));
+ }
+ }
+
+ public void setTracksRequirements(final Link[] tracksRequirements)
+ {
+ this.tracksRequirements.clear();
+
+ if (tracksRequirements != null)
+ {
+ this.tracksRequirements.addAll(Arrays.asList(tracksRequirements));
+ }
+ }
+
+ public void setVerified(final Boolean verified)
+ {
+ this.verified = verified;
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/Person.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/Person.java
new file mode 100644
index 0000000..2a3bb48
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/Person.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.lyo.oslc4j.bugzilla.resources;
+
+import java.net.URI;
+
+import org.eclipse.lyo.oslc4j.bugzilla.Constants;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcDescription;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcNamespace;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcPropertyDefinition;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcReadOnly;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcResourceShape;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcTitle;
+import org.eclipse.lyo.oslc4j.core.model.AbstractResource;
+
+
+
+/**
+ * A FOAF Person.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ * @see <a href="http://xmlns.com/foaf/spec/">FOAF Vocabulary Specification</a>
+ */
+@OslcNamespace(Constants.FOAF_NAMESPACE)
+@OslcResourceShape(title = "FOAF Person Resource Shape", describes = Constants.TYPE_PERSON)
+public class Person extends AbstractResource {
+ private URI uri = null;
+ private String name = null;
+ private String mbox = null;
+
+
+ public URI getUri() {
+ return uri;
+ }
+
+ public void setUri(URI uri) {
+ this.uri = uri;
+ }
+
+ @OslcDescription("A FOAF name ")
+ @OslcPropertyDefinition(Constants.FOAF_NAMESPACE + "name")
+ @OslcReadOnly
+ @OslcTitle("Name")
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ @OslcDescription("A FOAF Email address ")
+ @OslcPropertyDefinition(Constants.FOAF_NAMESPACE + "mbox")
+ @OslcReadOnly
+ @OslcTitle("Email Address")
+ public String getMbox() {
+ return mbox;
+ }
+
+ public void setMbox(String mbox) {
+ this.mbox = mbox;
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/Severity.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/Severity.java
new file mode 100644
index 0000000..06e182b
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/Severity.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Russell Boykin - initial API and implementation
+ * Alberto Giammaria - initial API and implementation
+ * Chris Peters - initial API and implementation
+ * Gianluca Bernardini - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.resources;
+
+public enum Severity
+{
+ Unclassified,
+ Minor,
+ Normal,
+ Major,
+ Critical,
+ Blocker
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/Type.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/Type.java
new file mode 100644
index 0000000..2b1a1fc
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/Type.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Russell Boykin - initial API and implementation
+ * Alberto Giammaria - initial API and implementation
+ * Chris Peters - initial API and implementation
+ * Gianluca Bernardini - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.resources;
+
+public enum Type
+{
+ Defect("Defect"),
+ Task("Task"),
+ Story("Story"),
+ Bug_Report("Bug Report"),
+ Feature_Request("Feature Request");
+
+ private String value;
+
+ Type(final String value)
+ {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ public static Type fromString(final String string)
+ {
+ final Type[] values = Type.values();
+ for (final Type value : values)
+ {
+ if (value.value.equals(string))
+ {
+ return value;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/package-info.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/package-info.java
new file mode 100644
index 0000000..240a027
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/resources/package-info.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Russell Boykin - initial API and implementation
+ * Alberto Giammaria - initial API and implementation
+ * Chris Peters - initial API and implementation
+ * Gianluca Bernardini - initial API and implementation
+ *******************************************************************************/
+@OslcSchema ({
+ @OslcNamespaceDefinition(prefix = OslcConstants.DCTERMS_NAMESPACE_PREFIX, namespaceURI = OslcConstants.DCTERMS_NAMESPACE),
+ @OslcNamespaceDefinition(prefix = OslcConstants.OSLC_CORE_NAMESPACE_PREFIX, namespaceURI = OslcConstants.OSLC_CORE_NAMESPACE),
+ @OslcNamespaceDefinition(prefix = OslcConstants.OSLC_DATA_NAMESPACE_PREFIX, namespaceURI = OslcConstants.OSLC_DATA_NAMESPACE),
+ @OslcNamespaceDefinition(prefix = OslcConstants.RDF_NAMESPACE_PREFIX, namespaceURI = OslcConstants.RDF_NAMESPACE),
+ @OslcNamespaceDefinition(prefix = OslcConstants.RDFS_NAMESPACE_PREFIX, namespaceURI = OslcConstants.RDFS_NAMESPACE),
+ @OslcNamespaceDefinition(prefix = Constants.CHANGE_MANAGEMENT_NAMESPACE_PREFIX, namespaceURI = Constants.CHANGE_MANAGEMENT_NAMESPACE),
+ @OslcNamespaceDefinition(prefix = Constants.BUGZILLA_NAMESPACE_PREFIX, namespaceURI = Constants.BUGZILLA_NAMESPACE),
+ @OslcNamespaceDefinition(prefix = Constants.FOAF_NAMESPACE_PREFIX, namespaceURI = Constants.FOAF_NAMESPACE),
+ @OslcNamespaceDefinition(prefix = Constants.QUALITY_MANAGEMENT_PREFIX, namespaceURI = Constants.QUALITY_MANAGEMENT_NAMESPACE),
+ @OslcNamespaceDefinition(prefix = Constants.REQUIREMENTS_MANAGEMENT_PREFIX, namespaceURI = Constants.REQUIREMENTS_MANAGEMENT_NAMESPACE),
+ @OslcNamespaceDefinition(prefix = Constants.SOFTWARE_CONFIGURATION_MANAGEMENT_PREFIX, namespaceURI = Constants.SOFTWARE_CONFIGURATION_MANAGEMENT_NAMESPACE)
+})
+package org.eclipse.lyo.oslc4j.bugzilla.resources;
+
+import org.eclipse.lyo.oslc4j.core.annotation.OslcNamespaceDefinition;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcSchema;
+import org.eclipse.lyo.oslc4j.core.model.OslcConstants;
+import org.eclipse.lyo.oslc4j.bugzilla.Constants;
+
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/BugzillaApplication.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/BugzillaApplication.java
new file mode 100644
index 0000000..a66d758
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/BugzillaApplication.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Michael Fiedler - initial API and implementation for Bugzilla adapter
+ *
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.services;
+
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.lyo.oslc4j.application.OslcWinkApplication;
+import org.eclipse.lyo.oslc4j.bugzilla.Constants;
+import org.eclipse.lyo.oslc4j.bugzilla.resources.BugzillaChangeRequest;
+import org.eclipse.lyo.oslc4j.bugzilla.resources.Person;
+import org.eclipse.lyo.oslc4j.core.exception.OslcCoreApplicationException;
+import org.eclipse.lyo.oslc4j.core.model.AllowedValues;
+import org.eclipse.lyo.oslc4j.core.model.Compact;
+import org.eclipse.lyo.oslc4j.core.model.CreationFactory;
+import org.eclipse.lyo.oslc4j.core.model.Dialog;
+import org.eclipse.lyo.oslc4j.core.model.Error;
+import org.eclipse.lyo.oslc4j.core.model.ExtendedError;
+import org.eclipse.lyo.oslc4j.core.model.OAuthConfiguration;
+import org.eclipse.lyo.oslc4j.core.model.OslcConstants;
+import org.eclipse.lyo.oslc4j.core.model.PrefixDefinition;
+import org.eclipse.lyo.oslc4j.core.model.Preview;
+import org.eclipse.lyo.oslc4j.core.model.Property;
+import org.eclipse.lyo.oslc4j.core.model.Publisher;
+import org.eclipse.lyo.oslc4j.core.model.QueryCapability;
+import org.eclipse.lyo.oslc4j.core.model.ResourceShape;
+import org.eclipse.lyo.oslc4j.core.model.Service;
+import org.eclipse.lyo.oslc4j.core.model.ServiceProvider;
+import org.eclipse.lyo.oslc4j.core.model.ServiceProviderCatalog;
+import org.eclipse.lyo.oslc4j.provider.jena.JenaProvidersRegistry;
+import org.eclipse.lyo.oslc4j.provider.json4j.Json4JProvidersRegistry;
+
+public class BugzillaApplication extends OslcWinkApplication {
+
+ private static final Set<Class<?>> RESOURCE_CLASSES = new HashSet<Class<?>>();
+ private static final Map<String, Class<?>> RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP = new HashMap<String, Class<?>>();
+
+ static
+ {
+ try
+ {
+ RESOURCE_CLASSES.addAll(JenaProvidersRegistry.getProviders());
+ RESOURCE_CLASSES.addAll(Json4JProvidersRegistry.getProviders());
+ RESOURCE_CLASSES.add(BugzillaChangeRequestService.class);
+ RESOURCE_CLASSES.add(Person.class);
+
+ RESOURCE_CLASSES.add(Class.forName("org.eclipse.lyo.server.oauth.webapp.services.ConsumersService"));
+ RESOURCE_CLASSES.add(Class.forName("org.eclipse.lyo.server.oauth.webapp.services.OAuthService"));
+
+ //Catalog resources.
+
+ RESOURCE_CLASSES.add(ServiceProviderCatalogService.class);
+ RESOURCE_CLASSES.add(ServiceProviderService.class);
+
+ //TRS resource
+ // Added in Lab 1.1
+ RESOURCE_CLASSES.add(TrackedResourceSetService.class);
+
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_ALLOWED_VALUES, AllowedValues.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_COMPACT, Compact.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_CREATION_FACTORY, CreationFactory.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_DIALOG, Dialog.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_ERROR, Error.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_EXTENDED_ERROR, ExtendedError.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_OAUTH_CONFIGURATION, OAuthConfiguration.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_PREFIX_DEFINITION, PrefixDefinition.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_PREVIEW, Preview.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_PROPERTY, Property.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_PUBLISHER, Publisher.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_QUERY_CAPABILITY, QueryCapability.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_RESOURCE_SHAPE, ResourceShape.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_SERVICE, Service.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_SERVICE_PROVIDER, ServiceProvider.class);
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(OslcConstants.PATH_SERVICE_PROVIDER_CATALOG, ServiceProviderCatalog.class);
+ } catch (ClassNotFoundException e)
+ {
+ e.printStackTrace();
+ System.err.println("BugzillaApplication failed to initialize");
+ }
+
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP.put(Constants.PATH_CHANGE_REQUEST, BugzillaChangeRequest.class);
+
+ }
+
+ public BugzillaApplication()
+ throws OslcCoreApplicationException,
+ URISyntaxException
+ {
+ super(RESOURCE_CLASSES,
+ OslcConstants.PATH_RESOURCE_SHAPES,
+ RESOURCE_SHAPE_PATH_TO_RESOURCE_CLASS_MAP);
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/BugzillaChangeRequestService.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/BugzillaChangeRequestService.java
new file mode 100644
index 0000000..44a1982
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/BugzillaChangeRequestService.java
@@ -0,0 +1,960 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Michael Fiedler - initial API and implementation for Bugzilla adapter
+ *
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.services;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+
+import org.eclipse.lyo.core.query.ParseException;
+import org.eclipse.lyo.core.query.Properties;
+import org.eclipse.lyo.core.query.QueryUtils;
+import org.eclipse.lyo.oslc4j.bugzilla.BugzillaManager;
+import org.eclipse.lyo.oslc4j.bugzilla.Constants;
+import org.eclipse.lyo.oslc4j.bugzilla.jbugzx.rpc.GetLegalValues;
+import org.eclipse.lyo.oslc4j.bugzilla.resources.BugzillaChangeRequest;
+import org.eclipse.lyo.oslc4j.bugzilla.resources.ChangeRequest;
+import org.eclipse.lyo.oslc4j.bugzilla.servlet.ServiceProviderCatalogSingleton;
+import org.eclipse.lyo.oslc4j.core.OSLC4JConstants;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcCreationFactory;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcDialog;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcDialogs;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcNamespaceDefinition;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcQueryCapability;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcSchema;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcService;
+import org.eclipse.lyo.oslc4j.core.model.Compact;
+import org.eclipse.lyo.oslc4j.core.model.OslcConstants;
+import org.eclipse.lyo.oslc4j.core.model.OslcMediaType;
+import org.eclipse.lyo.oslc4j.core.model.Preview;
+import org.eclipse.lyo.oslc4j.core.model.ServiceProvider;
+
+import com.j2bugzilla.base.Bug;
+import com.j2bugzilla.base.BugzillaConnector;
+import com.j2bugzilla.base.Product;
+import com.j2bugzilla.rpc.BugSearch;
+
+
+@OslcService(Constants.CHANGE_MANAGEMENT_DOMAIN)
+@Path("{productId}/changeRequests")
+public class BugzillaChangeRequestService
+
+{
+
+ @Context private HttpServletRequest httpServletRequest;
+ @Context private HttpServletResponse httpServletResponse;
+ @Context private UriInfo uriInfo;
+
+ public BugzillaChangeRequestService()
+ {
+ super();
+ }
+
+ @OslcDialogs(
+ {
+ @OslcDialog
+ (
+ title = "Change Request Selection Dialog",
+ label = "Change Request Selection Dialog",
+ uri = "/{productId}/changeRequests/selector",
+ hintWidth = "525px",
+ hintHeight = "325px",
+ resourceTypes = {Constants.TYPE_CHANGE_REQUEST},
+ usages = {OslcConstants.OSLC_USAGE_DEFAULT}
+ )
+
+ })
+ @OslcQueryCapability
+ (
+ title = "Change Request Query Capability",
+ label = "Change Request Catalog Query",
+ resourceShape = OslcConstants.PATH_RESOURCE_SHAPES + "/" + Constants.PATH_CHANGE_REQUEST,
+ resourceTypes = {Constants.TYPE_CHANGE_REQUEST},
+ usages = {OslcConstants.OSLC_USAGE_DEFAULT}
+ )
+
+ /**
+ * RDF/XML, XML and JSON representation of a change request collection
+ *
+ * TODO: add query support
+ *
+ * @param productId
+ * @param where
+ * @param select
+ * @param prefix
+ * @param pageString
+ * @param orderBy
+ * @param searchTerms
+ * @param paging
+ * @param pageSize
+ * @return
+ * @throws IOException
+ * @throws ServletException
+ */
+ @GET
+ @Produces({OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_XML, OslcMediaType.APPLICATION_JSON})
+ public List<BugzillaChangeRequest> getChangeRequests(@PathParam("productId") final String productId,
+ @QueryParam("oslc.where") final String where,
+ @QueryParam("oslc.select") final String select,
+ @QueryParam("oslc.prefix") final String prefix,
+ @QueryParam("page") final String pageString,
+ @QueryParam("oslc.orderBy") final String orderBy,
+ @QueryParam("oslc.searchTerms") final String searchTerms,
+ @QueryParam("oslc.paging") final String paging,
+ @QueryParam("oslc.pageSize") final String pageSize) throws IOException, ServletException
+ {
+ boolean isPaging = false;
+
+ if (paging != null) {
+ isPaging = Boolean.parseBoolean(paging);
+ }
+
+ int page=0;
+
+ if (null != pageString) {
+ page = Integer.parseInt(pageString);
+ }
+
+ int limit=10;
+
+ if (isPaging && pageSize != null) {
+ limit = Integer.parseInt(pageSize);
+ }
+
+ Map<String, String> prefixMap;
+
+ try {
+ prefixMap = QueryUtils.parsePrefixes(prefix);
+ } catch (ParseException e) {
+ throw new IOException(e);
+ }
+
+ addDefaultPrefixes(prefixMap);
+
+ Properties properties;
+
+ if (select == null) {
+ properties = QueryUtils.WILDCARD_PROPERTY_LIST;
+ } else {
+ try {
+ properties = QueryUtils.parseSelect(select, prefixMap);
+ } catch (ParseException e) {
+ throw new IOException(e);
+ }
+ }
+
+ Map<String, Object> propMap =
+ QueryUtils.invertSelectedProperties(properties);
+
+ final List<BugzillaChangeRequest> results =
+ BugzillaManager.getBugsByProduct(httpServletRequest, productId, page, limit,
+ where, prefixMap,
+ propMap, orderBy, searchTerms);
+
+ Object nextPageAttr = httpServletRequest.getAttribute(Constants.NEXT_PAGE);
+
+ if (! isPaging && nextPageAttr != null) {
+
+ String location =
+ uriInfo.getBaseUri().toString() + uriInfo.getPath() + '?' +
+ (where != null ? ("oslc.where=" + URLEncoder.encode(where, "UTF-8") + '&') : "") +
+ (select != null ? ("oslc.select=" + URLEncoder.encode(select, "UTF-8") + '&') : "") +
+ (prefix != null ? ("oslc.prefix=" + URLEncoder.encode(prefix, "UTF-8") + '&') : "") +
+ (orderBy != null ? ("oslc.orderBy=" + URLEncoder.encode(orderBy, "UTF-8") + '&') : "") +
+ (searchTerms != null ? ("oslc.searchTerms=" + URLEncoder.encode(searchTerms, "UTF-8") + '&') : "") +
+ "oslc.paging=true&oslc.pageSize=" + limit;
+
+ try {
+ throw new WebApplicationException(Response.temporaryRedirect(new URI(location)).build());
+ } catch (URISyntaxException e) {
+ // XXX - Can't happen
+ throw new IllegalStateException(e);
+ }
+ }
+
+ httpServletRequest.setAttribute(OSLC4JConstants.OSLC4J_SELECTED_PROPERTIES,
+ propMap);
+
+ if (nextPageAttr != null) {
+
+ String location =
+ uriInfo.getBaseUri().toString() + uriInfo.getPath() + '?' +
+ (where != null ? ("oslc.where=" + URLEncoder.encode(where, "UTF-8") + '&') : "") +
+ (select != null ? ("oslc.select=" + URLEncoder.encode(select, "UTF-8") + '&') : "") +
+ (prefix != null ? ("oslc.prefix=" + URLEncoder.encode(prefix, "UTF-8") + '&') : "") +
+ (orderBy != null ? ("oslc.orderBy=" + URLEncoder.encode(orderBy, "UTF-8") + '&') : "") +
+ (searchTerms != null ? ("oslc.searchTerms=" + URLEncoder.encode(searchTerms, "UTF-8") + '&') : "") +
+ "oslc.paging=true&oslc.pageSize=" + limit + "&page=" + nextPageAttr;
+
+ httpServletRequest.setAttribute(OSLC4JConstants.OSLC4J_NEXT_PAGE,
+ location);
+
+ }
+
+ return results;
+ }
+
+ private static void addDefaultPrefixes(final Map<String, String> prefixMap)
+ {
+ recursivelyCollectNamespaceMappings(prefixMap, BugzillaChangeRequest.class);
+ }
+
+ private static void recursivelyCollectNamespaceMappings(final Map<String, String> prefixMap,
+ final Class<? extends Object> resourceClass)
+ {
+ final OslcSchema oslcSchemaAnnotation = resourceClass.getPackage().getAnnotation(OslcSchema.class);
+
+ if (oslcSchemaAnnotation != null)
+ {
+ final OslcNamespaceDefinition[] oslcNamespaceDefinitionAnnotations = oslcSchemaAnnotation.value();
+
+ for (final OslcNamespaceDefinition oslcNamespaceDefinitionAnnotation : oslcNamespaceDefinitionAnnotations)
+ {
+ final String prefix = oslcNamespaceDefinitionAnnotation.prefix();
+ final String namespaceURI = oslcNamespaceDefinitionAnnotation.namespaceURI();
+
+ prefixMap.put(prefix, namespaceURI);
+ }
+ }
+
+ final Class<?> superClass = resourceClass.getSuperclass();
+
+ if (superClass != null)
+ {
+ recursivelyCollectNamespaceMappings(prefixMap,
+ superClass);
+ }
+
+ final Class<?>[] interfaces = resourceClass.getInterfaces();
+
+ if (interfaces != null)
+ {
+ for (final Class<?> interfac : interfaces)
+ {
+ recursivelyCollectNamespaceMappings(prefixMap,
+ interfac);
+ }
+ }
+ }
+
+ /**
+ * HTML representation of change request collection
+ *
+ * Forwards to changerequest_collection_html.jsp to build the html page
+ *
+ * @param productId
+ * @param where
+ * @param prefix
+ * @param pageString
+ * @param orderBy
+ * @param searchTerms
+ * @return
+ * @throws ServletException
+ * @throws IOException
+ */
+ @GET
+ @Produces({ MediaType.TEXT_HTML })
+ public Response getHtmlCollection(@PathParam("productId") final String productId,
+ @QueryParam("oslc.where") final String where,
+ @QueryParam("oslc.prefix") final String prefix,
+ @QueryParam("page") final String pageString,
+ @QueryParam("oslc.orderBy") final String orderBy,
+ @QueryParam("oslc.searchTerms") final String searchTerms) throws ServletException, IOException
+ {
+ int page=0;
+
+ if (null != pageString) {
+ page = Integer.parseInt(pageString);
+ }
+
+ int limit=20;
+
+ Map<String, String> prefixMap;
+
+ try {
+ prefixMap = QueryUtils.parsePrefixes(prefix);
+ } catch (ParseException e) {
+ throw new IOException(e);
+ }
+
+ addDefaultPrefixes(prefixMap);
+
+ Properties properties;
+
+ try {
+ properties = QueryUtils.parseSelect("dcterms:title", prefixMap);
+ } catch (ParseException e) {
+ throw new IOException(e);
+ }
+
+ Map<String, Object> propMap =
+ QueryUtils.invertSelectedProperties(properties);
+
+ final List<BugzillaChangeRequest> results =
+ BugzillaManager.getBugsByProduct(httpServletRequest, productId, page, limit,
+ where, prefixMap, propMap, orderBy,
+ searchTerms);
+
+ if (results != null) {
+ final String bugzillaUri = BugzillaManager.getBugzillaUri().toString();
+ httpServletRequest.setAttribute("results", results);
+ httpServletRequest.setAttribute("bugzillaUri", bugzillaUri);
+
+ httpServletRequest.setAttribute("queryUri",
+ uriInfo.getAbsolutePath().toString() + "?oslc.paging=true");
+
+ Object nextPageAttr = httpServletRequest.getAttribute(Constants.NEXT_PAGE);
+
+ if (nextPageAttr != null) {
+ httpServletRequest.setAttribute("nextPageUri",
+ uriInfo.getAbsolutePath().toString() + "?oslc.paging=true&amp;page=" + nextPageAttr);
+ }
+
+ ServiceProvider serviceProvider = ServiceProviderCatalogSingleton.getServiceProvider(httpServletRequest, productId);
+ httpServletRequest.setAttribute("serviceProvider", serviceProvider);
+
+ RequestDispatcher rd = httpServletRequest.getRequestDispatcher("/cm/changerequest_collection_html.jsp");
+ rd.forward(httpServletRequest,httpServletResponse);
+ }
+
+ throw new WebApplicationException(Status.NOT_FOUND);
+ }
+
+ /**
+ * RDF/XML, XML and JSON representation of a single change request
+ *
+ * @param productId
+ * @param changeRequestId
+ * @param propertiesString
+ * @param prefix
+ * @return
+ * @throws IOException
+ * @throws ServletException
+ * @throws URISyntaxException
+ */
+ @GET
+ @Path("{changeRequestId}")
+ @Produces({OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_XML, OslcMediaType.APPLICATION_JSON})
+ public BugzillaChangeRequest getChangeRequest(@PathParam("productId") final String productId,
+ @PathParam("changeRequestId") final String changeRequestId,
+ @QueryParam("oslc.properties") final String propertiesString,
+ @QueryParam("oslc.prefix") final String prefix) throws IOException, ServletException, URISyntaxException
+ {
+ Map<String, String> prefixMap;
+
+ try {
+ prefixMap = QueryUtils.parsePrefixes(prefix);
+ } catch (ParseException e) {
+ throw new IOException(e);
+ }
+
+ addDefaultPrefixes(prefixMap);
+
+ Properties properties;
+
+ if (propertiesString == null) {
+ properties = QueryUtils.WILDCARD_PROPERTY_LIST;
+ } else {
+ try {
+ properties = QueryUtils.parseSelect(propertiesString, prefixMap);
+ } catch (ParseException e) {
+ throw new IOException(e);
+ }
+ }
+
+ final Bug bug = BugzillaManager.getBugById(httpServletRequest, changeRequestId);
+
+ if (bug != null) {
+ BugzillaChangeRequest changeRequest = null;
+
+ changeRequest = BugzillaChangeRequest.fromBug(bug, httpServletRequest);
+
+ changeRequest.setServiceProvider(ServiceProviderCatalogSingleton.getServiceProvider(httpServletRequest, productId).getAbout());
+ changeRequest.setAbout(getAboutURI(productId + "/changeRequests/" + changeRequest.getIdentifier()));
+ setETagHeader(getETagFromChangeRequest(changeRequest), httpServletResponse);
+
+ httpServletRequest.setAttribute(OSLC4JConstants.OSLC4J_SELECTED_PROPERTIES,
+ QueryUtils.invertSelectedProperties(properties));
+
+ return changeRequest;
+ }
+
+ throw new WebApplicationException(Status.NOT_FOUND);
+ }
+
+ /**
+ * OSLC Compact representation of a single change request
+ *
+ * Contains a reference to the smallPreview method in this class for the preview document
+ *
+ * @param productId
+ * @param changeRequestId
+ * @return
+ * @throws URISyntaxException
+ * @throws IOException
+ * @throws ServletException
+ */
+ @GET
+ @Path("{changeRequestId}")
+ @Produces({OslcMediaType.APPLICATION_X_OSLC_COMPACT_XML})
+ public Compact getCompact(@PathParam("productId") final String productId,
+ @PathParam("changeRequestId") final String changeRequestId)
+ throws URISyntaxException, IOException, ServletException
+ {
+ final Bug bug = BugzillaManager.getBugById(httpServletRequest, changeRequestId);
+
+
+ if (bug != null) {
+ final Compact compact = new Compact();
+
+ BugzillaChangeRequest changeRequest = null;
+
+ changeRequest = BugzillaChangeRequest.fromBug(bug, httpServletRequest);
+
+ compact.setAbout(getAboutURI(productId + "/changeRequests/" + changeRequest.getIdentifier()));
+ compact.setTitle(changeRequest.getTitle());
+
+ String iconUri = BugzillaManager.getBugzillaUri() + "/images/favicon.ico";
+ compact.setIcon(new URI(iconUri));
+
+ //Create and set attributes for OSLC preview resource
+ final Preview smallPreview = new Preview();
+ smallPreview.setHintHeight("11em");
+ smallPreview.setHintWidth("45em");
+ smallPreview.setDocument(new URI(compact.getAbout().toString() + "/smallPreview"));
+ compact.setSmallPreview(smallPreview);
+
+ //Use the HTML representation of a change request as the large preview as well
+ final Preview largePreview = new Preview();
+ largePreview.setHintHeight("20em");
+ largePreview.setHintWidth("45em");
+ largePreview.setDocument(new URI(compact.getAbout().toString() + "/largePreview"));
+ compact.setLargePreview(largePreview);
+ return compact;
+ }
+
+ throw new WebApplicationException(Status.NOT_FOUND);
+ }
+
+ /**
+ * HTML representation for a single change request - redirect the request directly to Bugzilla
+ *
+ * @param productId
+ * @param changeRequestId
+ * @throws ServletException
+ * @throws IOException
+ * @throws URISyntaxException
+ */
+ @GET
+ @Path("{changeRequestId}")
+ @Produces({ MediaType.TEXT_HTML })
+ public Response getHtmlChangeRequest(@PathParam("productId") final String productId,
+ @PathParam("changeRequestId") final String changeRequestId) throws ServletException, IOException, URISyntaxException
+ {
+ String forwardUri = BugzillaManager.getBugzillaUri() + "show_bug.cgi?id=" + changeRequestId;
+ httpServletResponse.sendRedirect(forwardUri);
+ return Response.seeOther(new URI(forwardUri)).build();
+ }
+
+ /**
+ * OSLC delegated selection dialog for change requests
+ *
+ * If called without a "terms" parameter, forwards to changerequest_selector.jsp to
+ * build the html for the IFrame
+ *
+ * If called with a "terms" parameter, sends a Bug search to Bugzilla and then
+ * forwards to changerequest_filtered_json.jsp to build a JSON response
+ *
+ *
+ * @param terms
+ * @param productId
+ * @throws ServletException
+ * @throws IOException
+ */
+ @GET
+ @Path("selector")
+ @Consumes({ MediaType.TEXT_HTML, MediaType.WILDCARD })
+ public void changeRequestSelector(@QueryParam("terms") final String terms,
+ @PathParam("productId") final String productId) throws ServletException, IOException
+ {
+ int productIdNum = Integer.parseInt(productId);
+ httpServletRequest.setAttribute("productId", productIdNum);
+ httpServletRequest.setAttribute("bugzillaUri", BugzillaManager.getBugzillaUri());
+ httpServletRequest.setAttribute("selectionUri",uriInfo.getAbsolutePath().toString());
+
+ if (terms != null ) {
+ httpServletRequest.setAttribute("terms", terms);
+ sendFilteredBugsReponse(httpServletRequest, productId, terms);
+
+ } else {
+ try {
+ RequestDispatcher rd = httpServletRequest.getRequestDispatcher("/cm/changerequest_selector.jsp");
+ rd.forward(httpServletRequest, httpServletResponse);
+
+ } catch (Exception e) {
+ throw new ServletException(e);
+ }
+ }
+
+ }
+
+ /**
+ * OSLC small preview for a single change request
+ *
+ * Forwards to changerequest_preview_small.jsp to build the html
+ *
+ * @param productId
+ * @param changeRequestId
+ * @throws ServletException
+ * @throws IOException
+ * @throws URISyntaxException
+ */
+ @GET
+ @Path("{changeRequestId}/smallPreview")
+ @Produces({ MediaType.TEXT_HTML })
+ public void smallPreview(@PathParam("productId") final String productId,
+ @PathParam("changeRequestId") final String changeRequestId) throws ServletException, IOException, URISyntaxException
+ {
+
+ final Bug bug = BugzillaManager.getBugById(httpServletRequest, changeRequestId);
+
+ if (bug != null) {
+
+ BugzillaChangeRequest changeRequest = BugzillaChangeRequest.fromBug(bug, httpServletRequest);
+ changeRequest.setServiceProvider(ServiceProviderCatalogSingleton.getServiceProvider(httpServletRequest, productId).getAbout());
+ changeRequest.setAbout(getAboutURI(productId + "/changeRequests/" + changeRequest.getIdentifier()));
+
+ final String bugzillaUri = BugzillaManager.getBugzillaUri().toString();
+ httpServletRequest.setAttribute("changeRequest", changeRequest);
+ httpServletRequest.setAttribute("bugzillaUri", bugzillaUri);
+
+ RequestDispatcher rd = httpServletRequest.getRequestDispatcher("/cm/changerequest_preview_small.jsp");
+ rd.forward(httpServletRequest,httpServletResponse);
+ return;
+ }
+
+ throw new WebApplicationException(Status.NOT_FOUND);
+
+ }
+
+ /**
+ * OSLC large preview for a single change request
+ *
+ * Forwards to changerequest_preview_large.jsp to build the html
+ *
+ * @param productId
+ * @param changeRequestId
+ * @throws ServletException
+ * @throws IOException
+ * @throws URISyntaxException
+ */
+ @GET
+ @Path("{changeRequestId}/largePreview")
+ @Produces({ MediaType.TEXT_HTML })
+ public void getLargePreview(@PathParam("productId") final String productId,
+ @PathParam("changeRequestId") final String changeRequestId) throws ServletException, IOException, URISyntaxException
+ {
+ final Bug bug = BugzillaManager.getBugById(httpServletRequest, changeRequestId);
+
+ if (bug != null) {
+ BugzillaChangeRequest changeRequest = null;
+
+ changeRequest = BugzillaChangeRequest.fromBug(bug, httpServletRequest);
+ changeRequest.setServiceProvider(ServiceProviderCatalogSingleton.getServiceProvider(httpServletRequest, productId).getAbout());
+ changeRequest.setAbout(getAboutURI(productId + "/changeRequests/" + changeRequest.getIdentifier()));
+
+ final String bugzillaUri = BugzillaManager.getBugzillaUri().toString();
+
+ httpServletRequest.setAttribute("changeRequest", changeRequest);
+ httpServletRequest.setAttribute("bugzillaUri", bugzillaUri);
+ httpServletRequest.setAttribute("bugUri", bugzillaUri + "/show_bug.cgi?id=" + Integer.toString(bug.getID()));
+
+ RequestDispatcher rd = httpServletRequest.getRequestDispatcher("/cm/changerequest_preview_large.jsp");
+ rd.forward(httpServletRequest,httpServletResponse);
+ }
+
+ throw new WebApplicationException(Status.NOT_FOUND);
+
+ }
+
+
+ /**
+ * Create a single BugzillaChangeRequest via RDF/XML, XML or JSON POST
+ * @param productId
+ * @param changeRequest
+ * @return
+ * @throws IOException
+ * @throws ServletException
+ */
+ @OslcDialog
+ (
+ title = "Change Request Creation Dialog",
+ label = "Change Request Creation Dialog",
+ uri = "/{productId}/changeRequests/creator",
+ hintWidth = "600px",
+ hintHeight = "375px",
+ resourceTypes = {Constants.TYPE_CHANGE_REQUEST},
+ usages = {OslcConstants.OSLC_USAGE_DEFAULT}
+ )
+ @OslcCreationFactory
+ (
+ title = "Change Request Creation Factory",
+ label = "Change Request Creation",
+ resourceShapes = {OslcConstants.PATH_RESOURCE_SHAPES + "/" + Constants.PATH_CHANGE_REQUEST},
+ resourceTypes = {Constants.TYPE_CHANGE_REQUEST},
+ usages = {OslcConstants.OSLC_USAGE_DEFAULT}
+ )
+ @POST
+ @Consumes({OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_XML, OslcMediaType.APPLICATION_JSON})
+ @Produces({OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_XML, OslcMediaType.APPLICATION_JSON})
+ public Response addChangeRequest(@PathParam("productId") final String productId,
+ final BugzillaChangeRequest changeRequest) throws IOException, ServletException
+
+ {
+ //Create a new Bug from the incoming change request, retrieve the bug and then convert to a BugzillaChangeRequest
+ final String newBugId = BugzillaManager.createBug(httpServletRequest, changeRequest, productId);
+ final Bug newBug = BugzillaManager.getBugById(httpServletRequest, newBugId);
+
+ BugzillaChangeRequest newChangeRequest;
+
+ try {
+ newChangeRequest = BugzillaChangeRequest.fromBug(newBug, httpServletRequest);
+ } catch (Exception e) {
+ throw new WebApplicationException(e);
+ }
+ URI about = getAboutURI(productId + "/changeRequests/" + newChangeRequest.getIdentifier());
+ newChangeRequest.setServiceProvider(ServiceProviderCatalogSingleton.getServiceProvider(httpServletRequest, productId).getAbout());
+ newChangeRequest.setAbout(about);
+ setETagHeader(getETagFromChangeRequest(newChangeRequest), httpServletResponse);
+
+ return Response.created(about).entity(changeRequest).build();
+ }
+
+ /**
+ * OSLC delegated creation dialog for a single change request
+ *
+ * Forwards to changerequest_creator.jsp to build the html form
+ *
+ * @param productId
+ * @throws IOException
+ * @throws ServletException
+ */
+ @GET
+ @Path("creator")
+ @Consumes({MediaType.WILDCARD})
+ public void changeRequestCreator(@PathParam("productId") final String productId) throws IOException, ServletException
+ {
+ try {
+
+ BugzillaConnector bc = BugzillaManager.getBugzillaConnector(httpServletRequest);
+ Product product = BugzillaManager.getProduct(httpServletRequest, productId);
+
+ httpServletRequest.setAttribute("product", product);
+
+ GetLegalValues getComponentValues =
+ new GetLegalValues("component", product.getID());
+ bc.executeMethod(getComponentValues);
+ List<String> components = Arrays.asList(getComponentValues.getValues());
+ httpServletRequest.setAttribute("components", components);
+
+ GetLegalValues getOsValues = new GetLegalValues("op_sys", -1);
+ bc.executeMethod(getOsValues);
+ List<String> operatingSystems = Arrays.asList(getOsValues.getValues());
+ httpServletRequest.setAttribute("operatingSystems", operatingSystems);
+
+ GetLegalValues getPlatformValues = new GetLegalValues("platform", -1);
+ bc.executeMethod(getPlatformValues);
+ List<String> platforms = Arrays.asList(getPlatformValues.getValues());
+ httpServletRequest.setAttribute("platforms", platforms);
+
+ GetLegalValues getVersionValues = new GetLegalValues("version", product.getID());
+ bc.executeMethod(getVersionValues);
+ List<String> versions = Arrays.asList(getVersionValues.getValues());
+ httpServletRequest.setAttribute("versions", versions);
+
+ httpServletRequest.setAttribute("creatorUri", uriInfo.getAbsolutePath().toString());
+ httpServletRequest.setAttribute("bugzillaUri", BugzillaManager.getBugzillaUri());
+
+ RequestDispatcher rd = httpServletRequest.getRequestDispatcher("/cm/changerequest_creator.jsp");
+ rd.forward(httpServletRequest, httpServletResponse);
+
+ } catch (Exception e) {
+ throw new WebApplicationException(e);
+ }
+
+ }
+
+
+ /**
+ * Backend creator for the OSLC delegated creation dialog.
+ *
+ * Accepts the input in FormParams and returns a small JSON response
+ *
+ * @param productId
+ * @param component
+ * @param version
+ * @param summary
+ * @param op_sys
+ * @param platform
+ * @param description
+ */
+ @POST
+ @Path("creator")
+ @Consumes({ MediaType.APPLICATION_FORM_URLENCODED})
+ public void createHtmlChangeRequest( @PathParam("productId") final String productId,
+ @FormParam("component") final String component,
+ @FormParam("version") final String version,
+ @FormParam("summary") final String summary,
+ @FormParam("op_sys") final String op_sys,
+ @FormParam("platform") final String platform,
+ @FormParam("description") final String description)
+ {
+
+
+ try {
+ BugzillaChangeRequest changeRequest = new BugzillaChangeRequest();
+ changeRequest.setComponent(component);
+ changeRequest.setVersion(version);
+ changeRequest.setTitle(summary);
+ changeRequest.setOperatingSystem(op_sys);
+ changeRequest.setPlatform(platform);
+ changeRequest.setDescription(description);
+
+ final String newBugId = BugzillaManager.createBug(httpServletRequest, changeRequest, productId);
+
+
+ final Bug newBug = BugzillaManager.getBugById(httpServletRequest, newBugId);
+ final BugzillaChangeRequest newChangeRequest = BugzillaChangeRequest.fromBug(newBug, httpServletRequest);
+ URI about = getAboutURI(productId + "/changeRequests/" + newBugId);
+ newChangeRequest.setAbout(about);
+
+ httpServletRequest.setAttribute("changeRequest", newChangeRequest);
+ httpServletRequest.setAttribute("changeRequestUri", newChangeRequest.getAbout().toString());
+
+ // Send back to the form a small JSON response
+ httpServletResponse.setContentType("application/json");
+ httpServletResponse.setStatus(Status.CREATED.getStatusCode());
+ httpServletResponse.addHeader("Location", newChangeRequest.getAbout().toString());
+ PrintWriter out = httpServletResponse.getWriter();
+ out.print("{\"title\": \"" + getChangeRequestLinkLabel(newBug.getID(), summary) + "\"," +
+ "\"resource\" : \"" + about + "\"}");
+ out.close();
+
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new WebApplicationException(e);
+ }
+
+ }
+
+ /**
+ * Updates a single change request via RDF/XML, XML or JSON PUT
+ *
+ * Currently, update only supports adding OSLC CM link attributes to a
+ * Bug in the Bug comments
+ *
+ * @param eTagHeader
+ * @param changeRequestId
+ * @param changeRequest
+ * @return
+ * @throws IOException
+ * @throws ServletException
+ */
+ @PUT
+ @Consumes({OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_XML, OslcMediaType.APPLICATION_JSON})
+ @Path("{changeRequestId}")
+ public Response updateChangeRequest(@HeaderParam("If-Match") final String eTagHeader,
+ @PathParam("changeRequestId") final String changeRequestId,
+ final BugzillaChangeRequest changeRequest) throws IOException, ServletException
+ {
+
+ //Only adding links is supported right now
+
+ final Bug originalBug = BugzillaManager.getBugById(httpServletRequest, changeRequestId);
+
+ if (originalBug != null) {
+ try {
+ final BugzillaChangeRequest originalChangeRequest = BugzillaChangeRequest.fromBug(originalBug, httpServletRequest);
+ final String originalETag = getETagFromChangeRequest(originalChangeRequest);
+
+ changeRequest.setIdentifier(originalChangeRequest.getIdentifier());
+
+ if ((eTagHeader == null) || (originalETag.equals(eTagHeader))) {
+
+ BugzillaManager.updateBug(httpServletRequest,changeRequest);
+ final Bug updatedBug = BugzillaManager.getBugById(httpServletRequest, changeRequestId);
+ final BugzillaChangeRequest updatedChangeRequest = BugzillaChangeRequest.fromBug(updatedBug, httpServletRequest);
+
+ setETagHeader(getETagFromChangeRequest(updatedChangeRequest),httpServletResponse);
+ } else {
+ throw new WebApplicationException(Status.PRECONDITION_FAILED);
+ }
+
+ } catch (Exception e) {
+ throw new WebApplicationException(e);
+ }
+ } else {
+ throw new WebApplicationException(Status.NOT_FOUND);
+ }
+
+ return Response.ok().build();
+ }
+
+
+
+ private static void setETagHeader(final String eTagFromChangeRequest,
+ final HttpServletResponse httpServletResponse)
+ {
+ httpServletResponse.setHeader("ETag", eTagFromChangeRequest);
+ }
+
+
+ private static String getETagFromChangeRequest(final ChangeRequest changeRequest)
+ {
+ Long eTag = null;
+
+ if (changeRequest.getModified() != null) {
+ eTag = changeRequest.getModified().getTime();
+ } else if (changeRequest.getCreated() != null) {
+ eTag = changeRequest.getCreated().getTime();
+ } else {
+ eTag = new Long(0);
+ }
+
+ return eTag.toString();
+ }
+
+
+ /**
+ * Convert a list of Bugzilla Bugs to a list of BugzillaChangeRequests
+ *
+ * @param httpServletRequest
+ * @param bugList
+ * @param productId
+ * @return
+ */
+ protected List<BugzillaChangeRequest> changeRequestsFromBugList(final HttpServletRequest httpServletRequest, final List<Bug> bugList, final String productId)
+ {
+ List<BugzillaChangeRequest> results = new ArrayList<BugzillaChangeRequest>();
+
+ for (Bug bug : bugList) {
+ BugzillaChangeRequest changeRequest = null;
+ try {
+ changeRequest = BugzillaChangeRequest.fromBug(bug, httpServletRequest);
+ } catch (Exception e) {
+ throw new WebApplicationException(e);
+ }
+
+ if (changeRequest != null) {
+ changeRequest.setServiceProvider(ServiceProviderCatalogSingleton.getServiceProvider(httpServletRequest, productId).getAbout());
+ changeRequest.setAbout(getAboutURI(productId + "/changeRequests/"+ changeRequest.getIdentifier()));
+ results.add(changeRequest);
+ }
+ }
+ return results;
+ }
+
+
+
+ protected URI getAboutURI(final String fragment)
+ {
+ URI about;
+ try {
+ about = new URI(BugzillaManager.getBugzServiceBase() + "/" + fragment);
+ } catch (URISyntaxException e) {
+ throw new WebApplicationException(e);
+ }
+ return about;
+ }
+
+ /**
+ * Create and run a Bugzilla search and return the result.
+ *
+ * Forwards to changerequest_filtered_json.jsp to create the JSON response
+ *
+ * @param httpServletRequest
+ * @param productId
+ * @param terms
+ * @throws ServletException
+ * @throws IOException
+ */
+ private void sendFilteredBugsReponse(final HttpServletRequest httpServletRequest, final String productId, final String terms )
+ throws ServletException, IOException
+ {
+ try {
+ final BugzillaConnector bc = BugzillaManager.getBugzillaConnector(httpServletRequest);
+
+ BugSearch bugSearch = createBugSearch(terms);
+ bc.executeMethod(bugSearch);
+ List<Bug> bugList = bugSearch.getSearchResults();
+ List<BugzillaChangeRequest> results = changeRequestsFromBugList(httpServletRequest, bugList, productId);
+ httpServletRequest.setAttribute("results", results);
+
+ RequestDispatcher rd = httpServletRequest.getRequestDispatcher("/cm/changerequest_filtered_json.jsp");
+ rd.forward(httpServletRequest, httpServletResponse);
+
+ } catch (Exception e) {
+ throw new WebApplicationException(e);
+ }
+ }
+
+ protected BugSearch createBugSearch(final String summary)
+ {
+ BugSearch.SearchQuery summaryQuery = new BugSearch.SearchQuery(
+ BugSearch.SearchLimiter.SUMMARY, summary);
+ BugSearch.SearchQuery limitQuery = new BugSearch.SearchQuery(
+ BugSearch.SearchLimiter.LIMIT, "50");
+
+ BugSearch bugSearch = new BugSearch(summaryQuery, limitQuery);
+
+ return bugSearch;
+ }
+
+ public static String getChangeRequestLinkLabel(int bugId, String summary) {
+ return "Bug " + bugId + ": " + summary;
+ }
+
+
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/RootServicesService.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/RootServicesService.java
new file mode 100644
index 0000000..0baeb59
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/RootServicesService.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.services;
+
+import java.io.IOException;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.lyo.oslc4j.bugzilla.BugzillaManager;
+import org.eclipse.lyo.oslc4j.bugzilla.servlet.ServiceProviderCatalogSingleton;
+
+
+/**
+ * Jazz Root Services Service, see:
+ * https://jazz.net/wiki/bin/view/Main/RootServicesSpec
+ * https://jazz.net/wiki/bin/view/Main/RootServicesSpecAddendum2
+ */
+public class RootServicesService extends HttpServlet {
+
+ private static final long serialVersionUID = -8125286361811879744L;
+
+ /**
+ * Return a Rational Jazz compliant root services document
+ *
+ * See https://jazz.net/wiki/bin/view/Main/RootServicesSpec
+ */
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ request.setAttribute("baseUri", BugzillaManager.getBugzServiceBase());
+ request.setAttribute("catalogUri", ServiceProviderCatalogSingleton.getUri().toString());
+ request.setAttribute("oauthDomain", BugzillaManager.getServletBase());
+ final RequestDispatcher rd = request.getRequestDispatcher("/cm/rootservices_rdfxml.jsp");
+ rd.forward(request, response);
+ response.flushBuffer();
+ }
+}
+ \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/ServiceProviderCatalogService.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/ServiceProviderCatalogService.java
new file mode 100644
index 0000000..4103277
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/ServiceProviderCatalogService.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Russell Boykin - initial API and implementation
+ * Alberto Giammaria - initial API and implementation
+ * Chris Peters - initial API and implementation
+ * Gianluca Bernardini - initial API and implementation
+ * Michael Fiedler - implementation for Bugzilla adapter
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.services;
+
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.core.Response;
+
+import org.eclipse.lyo.oslc4j.core.annotation.OslcDialog;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcQueryCapability;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcService;
+import org.eclipse.lyo.oslc4j.core.model.Compact;
+import org.eclipse.lyo.oslc4j.core.model.OslcConstants;
+import org.eclipse.lyo.oslc4j.core.model.OslcMediaType;
+import org.eclipse.lyo.oslc4j.core.model.ServiceProviderCatalog;
+import org.eclipse.lyo.oslc4j.bugzilla.BugzillaManager;
+import org.eclipse.lyo.oslc4j.bugzilla.Constants;
+import org.eclipse.lyo.oslc4j.bugzilla.servlet.ServiceProviderCatalogSingleton;
+
+@OslcService(OslcConstants.OSLC_CORE_DOMAIN)
+@Path("catalog")
+public class ServiceProviderCatalogService
+{
+ @Context private HttpServletRequest httpServletRequest;
+ @Context private HttpServletResponse httpServletResponse;
+ @Context private UriInfo uriInfo;
+ @OslcDialog
+ (
+ title = "Service Provider Catalog Selection Dialog",
+ label = "Service Provider Catalog Selection Dialog",
+ uri = "/catalog",
+ hintWidth = "1000px",
+ hintHeight = "600px",
+ resourceTypes = {OslcConstants.TYPE_SERVICE_PROVIDER_CATALOG},
+ usages = {OslcConstants.OSLC_USAGE_DEFAULT}
+ )
+ @OslcQueryCapability
+ (
+ title = "Service Provider Catalog Query Capability",
+ label = "Service Provider Catalog Query",
+ resourceShape = OslcConstants.PATH_RESOURCE_SHAPES + "/" + OslcConstants.PATH_SERVICE_PROVIDER_CATALOG,
+ resourceTypes = {OslcConstants.TYPE_SERVICE_PROVIDER_CATALOG},
+ usages = {OslcConstants.OSLC_USAGE_DEFAULT}
+ )
+
+ /**
+ * Redirect requests to /catalog to /catalog/singleton
+ *
+ * By default, OSLC4J returns an OSLC query response for /catalog. We really just
+ * want the catalog itself which lives at /catalog/{serviceProviderCatalogId}
+ *
+ * @return
+ * @throws IOException
+ * @throws URISyntaxException
+ */
+ @GET
+ public Response getServiceProviderCatalogs() throws IOException, URISyntaxException
+ {
+ String forwardUri = uriInfo.getAbsolutePath() + "/singleton";
+ httpServletResponse.sendRedirect(forwardUri);
+ return Response.seeOther(new URI(forwardUri)).build();
+ }
+
+
+ /**
+ * Return the OSLC service provider catalog as RDF/XML, XML or JSON
+ *
+ * @return
+ */
+ @GET
+ @Path("{serviceProviderCatalogId}") // Required to distinguish from array result. But, ignored.
+ @Produces({OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_XML, OslcMediaType.APPLICATION_JSON})
+ public ServiceProviderCatalog getServiceProviderCatalog()
+ {
+ ServiceProviderCatalog catalog = ServiceProviderCatalogSingleton.getServiceProviderCatalog(httpServletRequest);
+
+ if (catalog != null) {
+
+ httpServletResponse.addHeader(Constants.HDR_OSLC_VERSION,"2.0");
+ return catalog;
+ }
+
+ throw new WebApplicationException(Status.NOT_FOUND);
+ }
+
+ /**
+ * Return the catalog singleton as OSLC compact XML
+ * @return
+ */
+ @GET
+ @Path("{serviceProviderCatalogId}") // Required to distinguish from array result. But, ignored.
+ @Produces({OslcMediaType.APPLICATION_X_OSLC_COMPACT_XML, OslcMediaType.APPLICATION_X_OSLC_COMPACT_JSON})
+ public Compact getCompact()
+ {
+ final ServiceProviderCatalog serviceProviderCatalog = ServiceProviderCatalogSingleton.getServiceProviderCatalog(httpServletRequest);
+
+ if (serviceProviderCatalog != null) {
+
+
+ final Compact compact = new Compact();
+
+ compact.setAbout(serviceProviderCatalog.getAbout());
+ compact.setShortTitle(serviceProviderCatalog.getTitle());
+ compact.setTitle(serviceProviderCatalog.getTitle());
+
+ // TODO - Need icon for ServiceProviderCatalog compact.
+ httpServletResponse.addHeader("Oslc-Core-Version","2.0");
+ return compact;
+ }
+
+ throw new WebApplicationException(Status.NOT_FOUND);
+ }
+
+ /**
+ * Return the catalog singleton as HTML
+ *
+ * Forwards to serviceprovidercatalog_html.jsp to build the html
+ *
+ * @param serviceProviderId
+ */
+ @GET
+ @Path("{serviceProviderId}")
+ @Produces(MediaType.TEXT_HTML)
+ public void getHtmlServiceProvider(@PathParam("serviceProviderId") final String serviceProviderId)
+ {
+ ServiceProviderCatalog catalog = ServiceProviderCatalogSingleton.getServiceProviderCatalog(httpServletRequest);
+
+
+ if (catalog !=null )
+ {
+ httpServletRequest.setAttribute("bugzillaUri", BugzillaManager.getBugzillaUri());
+ httpServletRequest.setAttribute("catalog",catalog);
+
+ RequestDispatcher rd = httpServletRequest.getRequestDispatcher("/cm/serviceprovidercatalog_html.jsp");
+ try {
+ rd.forward(httpServletRequest, httpServletResponse);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new WebApplicationException(e);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/ServiceProviderService.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/ServiceProviderService.java
new file mode 100644
index 0000000..3d55d30
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/ServiceProviderService.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Russell Boykin - initial API and implementation
+ * Alberto Giammaria - initial API and implementation
+ * Chris Peters - initial API and implementation
+ * Gianluca Bernardini - initial API and implementation
+ * Michael Fiedler - implementation for Bugzilla adapter
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.services;
+
+
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.lyo.oslc4j.core.annotation.OslcDialog;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcQueryCapability;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcService;
+import org.eclipse.lyo.oslc4j.core.model.Compact;
+import org.eclipse.lyo.oslc4j.core.model.OslcConstants;
+import org.eclipse.lyo.oslc4j.core.model.OslcMediaType;
+import org.eclipse.lyo.oslc4j.core.model.Service;
+import org.eclipse.lyo.oslc4j.core.model.ServiceProvider;
+import org.eclipse.lyo.oslc4j.bugzilla.BugzillaManager;
+import org.eclipse.lyo.oslc4j.bugzilla.servlet.ServiceProviderCatalogSingleton;
+
+
+@OslcService(OslcConstants.OSLC_CORE_DOMAIN)
+@Path("serviceProviders")
+public class ServiceProviderService
+{
+ @Context private HttpServletRequest httpServletRequest;
+ @Context private HttpServletResponse httpServletResponse;
+
+
+ /**
+ * RDF/XML, XML and JSON representations of an OSLC Service Provider collection
+ * @return
+ */
+
+ @OslcDialog
+ (
+ title = "Service Provider Selection Dialog",
+ label = "Service Provider Selection Dialog",
+ uri = "",
+ hintWidth = "1000px",
+ hintHeight = "600px",
+ resourceTypes = {OslcConstants.TYPE_SERVICE_PROVIDER},
+ usages = {OslcConstants.OSLC_USAGE_DEFAULT}
+ )
+ @OslcQueryCapability
+ (
+ title = "Service Provider Query Capability",
+ label = "Service Provider Query",
+ resourceShape = OslcConstants.PATH_RESOURCE_SHAPES + "/" + OslcConstants.PATH_SERVICE_PROVIDER,
+ resourceTypes = {OslcConstants.TYPE_SERVICE_PROVIDER},
+ usages = {OslcConstants.OSLC_USAGE_DEFAULT}
+ )
+ @GET
+ @Produces({OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_XML, OslcMediaType.APPLICATION_JSON})
+ public ServiceProvider[] getServiceProviders()
+ {
+ httpServletResponse.addHeader("Oslc-Core-Version","2.0");
+ return ServiceProviderCatalogSingleton.getServiceProviders(httpServletRequest);
+ }
+
+ /**
+ * RDF/XML, XML and JSON representations of a single OSLC Service Provider
+ *
+ * @param serviceProviderId
+ * @return
+ */
+ @GET
+ @Path("{serviceProviderId}")
+ @Produces({OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_XML, OslcMediaType.APPLICATION_JSON})
+ public ServiceProvider getServiceProvider(@PathParam("serviceProviderId") final String serviceProviderId)
+ {
+ httpServletResponse.addHeader("Oslc-Core-Version","2.0");
+ return ServiceProviderCatalogSingleton.getServiceProvider(httpServletRequest, serviceProviderId);
+ }
+
+ /**
+ * OSLC compact XML representation of a single OSLC Service Provider
+ *
+ * @param serviceProviderId
+ * @return
+ */
+ @GET
+ @Path("{serviceProviderId}")
+ @Produces({OslcMediaType.APPLICATION_X_OSLC_COMPACT_XML, OslcMediaType.APPLICATION_X_OSLC_COMPACT_JSON})
+ public Compact getCompact(@PathParam("serviceProviderId") final String serviceProviderId)
+ {
+ final ServiceProvider serviceProvider = ServiceProviderCatalogSingleton.getServiceProvider(httpServletRequest, serviceProviderId);
+
+ if (serviceProvider != null) {
+
+ final Compact compact = new Compact();
+
+ compact.setAbout(serviceProvider.getAbout());
+ compact.setShortTitle(serviceProvider.getTitle());
+ compact.setTitle(serviceProvider.getTitle());
+
+ // TODO - Need icon for ServiceProvider compact.
+
+ httpServletResponse.addHeader("Oslc-Core-Version","2.0");
+ return compact;
+ }
+
+ throw new WebApplicationException(Status.NOT_FOUND);
+ }
+
+ /**
+ * HTML representation of a single OSLC Service Provider
+ *
+ * Forwards to serviceprovider_html.jsp to create the html document
+ *
+ * @param serviceProviderId
+ */
+ @GET
+ @Path("{serviceProviderId}")
+ @Produces(MediaType.TEXT_HTML)
+ public void getHtmlServiceProvider(@PathParam("serviceProviderId") final String serviceProviderId)
+ {
+ ServiceProvider serviceProvider = ServiceProviderCatalogSingleton.getServiceProvider(httpServletRequest, serviceProviderId);
+
+ Service [] services = serviceProvider.getServices();
+
+ if (services !=null && services.length > 0)
+ {
+ //Bugzilla adapter should only have one Service per ServiceProvider
+ httpServletRequest.setAttribute("bugzillaUri", BugzillaManager.getBugzillaUri());
+ httpServletRequest.setAttribute("service", services[0]);
+ httpServletRequest.setAttribute("serviceProvider", serviceProvider);
+
+ RequestDispatcher rd = httpServletRequest.getRequestDispatcher("/cm/serviceprovider_html.jsp");
+ try {
+ rd.forward(httpServletRequest, httpServletResponse);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new WebApplicationException(e);
+ }
+ }
+ }
+
+
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/TrackedResourceSetService.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/TrackedResourceSetService.java
new file mode 100644
index 0000000..ec337ba
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/services/TrackedResourceSetService.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * * Contributors:
+ *
+ * Susumu Fukuda - Initial implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.services;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.eclipse.lyo.core.trs.AbstractChangeLog;
+import org.eclipse.lyo.core.trs.Base;
+import org.eclipse.lyo.core.trs.ChangeLog;
+import org.eclipse.lyo.core.trs.EmptyChangeLog;
+import org.eclipse.lyo.core.trs.TRSConstants;
+import org.eclipse.lyo.core.trs.TrackedResourceSet;
+import org.eclipse.lyo.oslc4j.bugzilla.BugzillaManager;
+import org.eclipse.lyo.oslc4j.bugzilla.trs.ChangeBugzillaHistories;
+import org.eclipse.lyo.oslc4j.core.model.OslcMediaType;
+
+/*
+ * Added in Lab 1.1, Modified in Lab 1.3.
+ */
+@Path("/trs")
+public class TrackedResourceSetService {
+
+ public TrackedResourceSetService() {
+ }
+
+ @Context private HttpServletRequest httpServletRequest;
+ @Context private HttpServletResponse httpServletResponse;
+ @Context private UriInfo uriInfo;
+
+ /*
+ * Added in Lab 1.1
+ */
+ @GET
+ @Produces({"text/plain", "text/html"})
+ public String getTrackedResourceSetText() {
+ return "Hello TRS service.";
+ }
+
+ /*
+ * Added in Lab 1.3
+ */
+ @GET
+ @Produces({OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_XML, OslcMediaType.APPLICATION_JSON})
+ public TrackedResourceSet getTrackedResourceSet() {
+
+ TrackedResourceSet result = new TrackedResourceSet();
+ result.setAbout(URI.create(BugzillaManager.getBugzServiceBase() + "/trs"));//$NON-NLS-1$
+ result.setBase(URI.create(BugzillaManager.getBugzServiceBase() + "/trs/"+TRSConstants.TRS_TERM_BASE));//$NON-NLS-1$
+
+ ChangeBugzillaHistories.buildBaseResourcesAndChangeLogs(httpServletRequest);
+ AbstractChangeLog changeLog = (AbstractChangeLog)ChangeBugzillaHistories.getChangeLog("1", httpServletRequest);
+ if (changeLog == null) {
+ changeLog = new EmptyChangeLog();
+ }
+ result.setChangeLog(changeLog);
+ return result;
+ }
+
+ /*
+ * Added in Lab 1.3
+ */
+ @Path(TRSConstants.TRS_TERM_BASE)
+ @GET
+ @Produces({OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_XML, OslcMediaType.APPLICATION_JSON})
+ public Base getBase() {
+ URI requestURI = uriInfo.getRequestUri();
+ boolean endsWithSlash = requestURI.getPath().endsWith("/");
+ String redirectLocation = requestURI.toString() + (endsWithSlash ? "1" : "/1");
+ try {
+ throw new WebApplicationException(Response.temporaryRedirect(new URI(redirectLocation)).build());
+ } catch (URISyntaxException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /*
+ * Added in Lab 1.3
+ */
+ @GET
+ @Path(TRSConstants.TRS_TERM_BASE+"/{page}")
+ @Produces({OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_XML, OslcMediaType.APPLICATION_JSON})
+ public Base getBasePage(
+ @PathParam("page") String pagenum ) {
+ return ChangeBugzillaHistories.getBaseResource(pagenum, httpServletRequest);
+ }
+
+ /*
+ * Added in Lab 1.3
+ */
+ @Path(TRSConstants.TRS_TERM_CHANGE_LOG)
+ @GET
+ @Produces({OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_XML, OslcMediaType.APPLICATION_JSON})
+ public ChangeLog getChangeLog() {
+ URI requestURI = uriInfo.getRequestUri();
+ boolean endsWithSlash = requestURI.getPath().endsWith("/");
+ String redirectLocation = requestURI.toString() + (endsWithSlash ? "1" : "/1");
+ try {
+ throw new WebApplicationException(Response.temporaryRedirect(new URI(redirectLocation)).build());
+ } catch (URISyntaxException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /*
+ * Added in Lab 1.3
+ */
+ @GET
+ @Path(TRSConstants.TRS_TERM_CHANGE_LOG+"/{page}")
+ @Produces({OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_XML, OslcMediaType.APPLICATION_JSON})
+ public ChangeLog getChangeLogPage(
+ @PathParam("page") String pagenum ) {
+ return ChangeBugzillaHistories.getChangeLog(pagenum, httpServletRequest);
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/AbstractAdapterCredentialsFilter.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/AbstractAdapterCredentialsFilter.java
new file mode 100644
index 0000000..7f8655f
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/AbstractAdapterCredentialsFilter.java
@@ -0,0 +1,507 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * * Contributors:
+ *
+ * Susumu Fukuda - Initial implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.servlet;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+import net.oauth.OAuth;
+import net.oauth.OAuthAccessor;
+import net.oauth.OAuthException;
+import net.oauth.OAuthMessage;
+import net.oauth.OAuthProblemException;
+import net.oauth.http.HttpMessage;
+import net.oauth.server.OAuthServlet;
+
+import org.eclipse.lyo.oslc4j.bugzilla.exception.UnauthorizedException;
+import org.eclipse.lyo.server.oauth.core.Application;
+import org.eclipse.lyo.server.oauth.core.AuthenticationException;
+import org.eclipse.lyo.server.oauth.core.OAuthConfiguration;
+import org.eclipse.lyo.server.oauth.core.OAuthRequest;
+import org.eclipse.lyo.server.oauth.core.consumer.ConsumerStore;
+import org.eclipse.lyo.server.oauth.core.consumer.LyoOAuthConsumer;
+import org.eclipse.lyo.server.oauth.core.token.LRUCache;
+import org.eclipse.lyo.server.oauth.core.token.SimpleTokenStrategy;
+
+/**
+ * <h3>Overview</h3>
+ * Purpose: Provide a JEE Servlet filter base implementation for accepting
+ * both HTTP basic and OAuth provider authentication, connecting your tool using the
+ * credentials, and managing the connections.
+ *
+ * <p>With this credentitals filter:<ul>
+ * <li>Your Webapp can accepts HTTP Basic authentication
+ * <li>Your Webapp can works as an OAuth provider
+ * </ul>
+ * <p>Once user entered credentials via HTTP Basic auth or OAuth, it
+ * is passed to a callback method {@link #getCredentialsFromRequest(HttpServletRequest)}
+ * or {@link #getCredentialsForOAuth(String, String)} so that your implementation
+ * can build a Credentials object from the given data.
+ * And then, next callback method {@link #login(Object, HttpServletRequest)} is invoked for
+ * authenticate the credentials and building connection to your back-end tool.
+ * Concrete types of the credentials and the connection can be specified as type
+ * parameters of this class.
+ *
+ * <p>While processing a request, the credentials and the connection are available
+ * as attributes of the request. Your subsequent process such as {@link HttpServlet#service(ServletRequest, ServletResponse)}
+ * can extract and use them for accessing your tool. You can use {@link #getConnector(HttpServletRequest)}
+ * and {@link #getCredentials(HttpServletRequest)} to retrieve them from the request.
+ *
+ * <h3>Usage</h3>
+ * <p>You have to subclass this class and give implementations for the following methods:
+ * <ul>
+ * <li>{@link #login(Object, HttpServletRequest)}
+ * <li>{@link #getCredentialsFromRequest(HttpServletRequest)}
+ * <li>{@link #getCredentialsForOAuth(String, String)}
+ * <li>{@link #isAdminSession(String, Object, HttpServletRequest)}
+ * <li>{@link #createConsumerStore()}
+ * <li>{@link #logout(Object, HttpSession)} (optional)
+ * </ul>
+ * Then, add the follwoing filter-mapping to your web.xml:
+ * <pre>
+ * &lt;filter&gt;
+ * &lt;display-name&gt;[YOUR FILTER CLASS NAME (MyFilter)]&lt;/display-name&gt;
+ * &lt;filter-name&gt;[YOUR FILTER CLASS NAME (MyFilter)]&lt;/filter-name&gt;
+ * &lt;filter-class&gt;[FULLY QUALIFIED YOUR FILTER CLASS NAME (com.example.MyFilter)]&lt;/filter-class&gt;
+ * &lt;/filter&gt;
+ * &lt;filter-mapping&gt;
+ * &lt;filter-name&gt;[YOUR FILTER CLASS NAME (MyFilter)]&lt;/filter-name&gt;
+ * &lt;url-pattern&gt;/services/*&lt;/url-pattern&gt;
+ * &lt;/filter-mapping&gt;
+ * </pre>
+ *
+ * @param <Connection> Type for connection to your tool
+ * @param <Credentials> Type for credentials for your tool. (e.g. UsernamePasswordCredentials)
+ */
+abstract public class AbstractAdapterCredentialsFilter<Credentials, Connection> implements Filter {
+
+ private static final String ATTRIBUTE_BASE = "org.eclipse.lyo.server.oauth.core.utils.";
+ protected static final String CONNECTOR_ATTRIBUTE = ATTRIBUTE_BASE + "Connector";
+ protected static final String CREDENTIALS_ATTRIBUTE = ATTRIBUTE_BASE + "Credentials";
+ protected static final String ADMIN_SESSION_ATTRIBUTE = ATTRIBUTE_BASE + "AdminSession";
+ protected static final String JAZZ_INVALID_EXPIRED_TOKEN_OAUTH_PROBLEM = "invalid_expired_token";
+ protected static final String OAUTH_EMPTY_TOKEN_KEY = new String("OAUTH_EMPTY_TOKEN_KEY");
+
+ private final LRUCache<String, Connection> keyToConnectorCache = new LRUCache<String, Connection>(200);
+
+ final private String displayName;
+ final private String realm;
+
+ /**
+ *
+ * @param displayName
+ * @param realm
+ */
+ protected AbstractAdapterCredentialsFilter(String displayName, String realm) {
+ this.displayName = displayName;
+ this.realm = realm;
+ }
+
+ /**
+ * Extract credentials from the request and return it.
+ * @param request {@link HttpServletRequest}
+ * @return credentials
+ * @throws UnauthorizedException
+ */
+ abstract protected Credentials getCredentialsFromRequest(HttpServletRequest request) throws UnauthorizedException;
+
+ /**
+ * Create a Credentials object from given user id and password.
+ *
+ * <p>For OAuth two-legged request, the <code>id</code> is set to {@link #OAUTH_EMPTY_TOKEN_KEY}
+ * object. Implementor can compare the value using <code>==</code> to identify the request.
+ * In the request the consumer key is set to the <code>password</code>. So you might find a functional
+ * user associated to the consumer key with the value.
+ * @param id user id or {@link #OAUTH_EMPTY_TOKEN_KEY}
+ * @param password password or OAuth consumer key
+ * @return credentials
+ */
+ abstract protected Credentials getCredentialsForOAuth(String id, String password);
+
+ /**
+ * Create connection to your tool using the given credentials, and returns the connection.
+ * @param crdentials credentials for login
+ * @param request {@link HttpServletRequest}
+ * @return connection that represents the successful login session
+ * @throws UnauthorizedException
+ * @throws ServletException
+ */
+ abstract protected Connection login(Credentials crdentials, HttpServletRequest request) throws UnauthorizedException, ServletException;
+
+ /**
+ * Logout
+ * @param loginSession
+ * @param session
+ */
+ protected void logout(Connection loginSession, HttpSession session) {
+ // do nothing by default
+ }
+
+ /**
+ * Tell if this is an admin session. For admin session, Lyo provides user-interface to
+ * accept provisional authentication key.
+ * @param id
+ * @param session
+ * @param request
+ * @return
+ */
+ abstract protected boolean isAdminSession(String id, Connection session, HttpServletRequest request);
+
+ /**
+ * Invoked from this class to create {@link ConsumerStore} for OAuth keys.
+ * Typical implementation can be:
+ * <pre>return new FileSystemConsumerStore("YourOAuthStore.xml");
+ * </pre>
+ * @return
+ * @throws Exception
+ */
+ abstract protected ConsumerStore createConsumerStore() throws Exception;
+
+ /**
+ * get Connector assigned to this request
+ *
+ * The connector should be placed in the session by the CredentialsFilter servlet filter
+ *
+ * @param request
+ * @return connector
+ */
+ public static <T> T getConnector(HttpServletRequest request)
+ {
+ //connector should never be null if CredentialsFilter is doing its job
+ @SuppressWarnings("unchecked")
+ T connector = (T) request.getAttribute(CONNECTOR_ATTRIBUTE);
+ return connector;
+ }
+
+ /**
+ * Get Credentials for this session
+ * @param request
+ * @return credentials
+ */
+ public static <T> T getCredentials(HttpServletRequest request)
+ {
+ @SuppressWarnings("unchecked")
+ T credentials = (T) request.getSession().getAttribute(CREDENTIALS_ATTRIBUTE);
+ return credentials;
+ }
+
+ protected String getOAuthRealm() {
+ return realm;
+ }
+ protected String getDisplayName() {
+ return displayName;
+ }
+
+
+ @Override
+ public void destroy() {
+
+ }
+
+ /**
+ * Check for OAuth or BasicAuth credentials and challenge if not found.
+ *
+ * Store the Connector in the HttpSession for retrieval in the REST services.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+ FilterChain chain) throws IOException, ServletException {
+
+ if(servletRequest instanceof HttpServletRequest && servletResponse instanceof HttpServletResponse) {
+ HttpServletRequest request = (HttpServletRequest) servletRequest;
+ HttpServletResponse response = (HttpServletResponse) servletResponse;
+
+ boolean isTwoLeggedOAuthRequest = false;
+ String twoLeggedOAuthConsumerKey = null;
+
+ //Don't protect requests to oauth service. TODO: possibly do this in web.xml
+ if (! request.getPathInfo().startsWith("/oauth"))
+ {
+
+ // First check if this is an OAuth request.
+ try {
+ try {
+ OAuthMessage message = OAuthServlet.getMessage(request, null);
+ // test if this is a valid two-legged oauth request
+ if ("".equals(message.getToken())) {
+ validateTwoLeggedOAuthMessage(message);
+ isTwoLeggedOAuthRequest = true;
+ twoLeggedOAuthConsumerKey = message.getConsumerKey();
+ }
+
+ if (!isTwoLeggedOAuthRequest && message.getToken() != null) {
+ OAuthRequest oAuthRequest = new OAuthRequest(request);
+ oAuthRequest.validate();
+ Connection connector = keyToConnectorCache.get(message.getToken());
+ if (connector == null) {
+ throw new OAuthProblemException(
+ OAuth.Problems.TOKEN_REJECTED);
+ }
+
+ request.getSession().setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ }
+ } catch (OAuthProblemException e) {
+ if (OAuth.Problems.TOKEN_REJECTED.equals(e.getProblem()))
+ throwInvalidExpiredException(e);
+ else
+ throw e;
+ }
+ } catch (OAuthException e) {
+ OAuthServlet.handleException(response, e, getOAuthRealm());
+ return;
+ } catch (URISyntaxException e) {
+ throw new ServletException(e);
+ }
+
+ // This is not an OAuth request. Check for basic access authentication.
+ HttpSession session = request.getSession();
+ Connection connector = (Connection) session.getAttribute(CONNECTOR_ATTRIBUTE);
+ if (connector == null) {
+ try {
+ Credentials credentials;
+ if (isTwoLeggedOAuthRequest) {
+ connector = keyToConnectorCache.get("");
+ if (connector == null) {
+ credentials = getCredentialsForOAuth(OAUTH_EMPTY_TOKEN_KEY, twoLeggedOAuthConsumerKey);
+ connector = login(credentials, request);
+ keyToConnectorCache.put("", connector);
+ }
+ credentials = null; // TODO; Do we need to keep the credentials for this path ??
+ } else {
+ credentials = (Credentials) request.getSession().getAttribute(CREDENTIALS_ATTRIBUTE);
+ if (credentials == null)
+ {
+ credentials = getCredentialsFromRequest(request);
+ if (credentials == null) {
+ throw new UnauthorizedException();
+ }
+ }
+ connector = login(credentials, request);
+ }
+ session.setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ session.setAttribute(CREDENTIALS_ATTRIBUTE, credentials);
+
+ } catch (UnauthorizedException e)
+ {
+ sendUnauthorizedResponse(response, e);
+ System.err.println(e.getMessage());
+ return;
+ } catch (ServletException ce)
+ {
+ throw ce;
+ }
+ }
+
+ if (connector != null) {
+ doChainDoFilterWithConnector(request, response, chain, connector);
+ return;
+ }
+
+ }
+ }
+
+ chain.doFilter(servletRequest, servletResponse);
+ }
+
+ /**
+ * The default implementation is:
+ * <pre>
+ * request.setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ * chain.doFilter(request, response);</pre>
+ *
+ * Subclass may invoke the <code>chain.doFilter()</code> directly instead of invoking super method.
+ *
+ * @param request {@link HttpServletRequest}
+ * @param response {@link HttpServletResponse}
+ * @param chain {@link FilterChain}
+ * @param sessionConnector {@link Connector} to be used for processing rest of the chain (i.e. REST request)
+ * @throws IOException
+ * @throws ServletException
+ */
+ protected void doChainDoFilterWithConnector(HttpServletRequest request,
+ HttpServletResponse response, FilterChain chain, Connection connector) throws IOException, ServletException {
+ request.setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ chain.doFilter(request, response);
+ }
+
+ private void validateTwoLeggedOAuthMessage(OAuthMessage message)
+ throws IOException, OAuthException,
+ URISyntaxException {
+ OAuthConfiguration config = OAuthConfiguration.getInstance();
+ LyoOAuthConsumer consumer = config.getConsumerStore().getConsumer(message.getConsumerKey());
+ if (consumer != null && consumer.isTrusted()) {
+ // The request can be a two-legged oauth request because it's a trusted consumer
+ // Validate the message with an empty token and an empty secret
+ OAuthAccessor accessor = new OAuthAccessor(consumer);
+ accessor.requestToken = "";
+ accessor.tokenSecret = "";
+ config.getValidator().validateMessage(message, accessor);
+ } else {
+ throw new OAuthProblemException(
+ OAuth.Problems.TOKEN_REJECTED);
+ }
+ }
+
+ private HttpSessionListener listener = new HttpSessionListener() {
+ @Override
+ public void sessionDestroyed(HttpSessionEvent se) {
+ HttpSession session = se.getSession();
+ @SuppressWarnings("unchecked")
+ Connection loginSession = (Connection) session.getAttribute(CONNECTOR_ATTRIBUTE);
+ logout(loginSession, session);
+ }
+
+ @Override
+ public void sessionCreated(HttpSessionEvent se) {
+ // nothing
+ }
+ };
+
+ @Override
+ public void init(FilterConfig arg0) throws ServletException {
+ OAuthConfiguration config = OAuthConfiguration.getInstance();
+
+ // Add session listener
+ arg0.getServletContext().addListener(listener);
+
+ // Validates a user's ID and password.
+ config.setApplication(new Application() {
+ @Override
+ public void login(HttpServletRequest request, String id,
+ String password) throws AuthenticationException {
+ try {
+ Credentials creds = getCredentialsForOAuth(id, password);
+ request.getSession().setAttribute(CREDENTIALS_ATTRIBUTE, creds);
+
+ Connection bc = AbstractAdapterCredentialsFilter.this.login(creds, request);
+ request.setAttribute(CONNECTOR_ATTRIBUTE, bc);
+
+ boolean isAdmin = AbstractAdapterCredentialsFilter.this.isAdminSession(id, bc, request);
+ request.getSession().setAttribute(ADMIN_SESSION_ATTRIBUTE, isAdmin);
+ } catch (Exception e) {
+ throw new AuthenticationException(e.getCause().getMessage(), e);
+ }
+ }
+
+ @Override
+ public String getName() {
+ // Display name for this application.
+ return getDisplayName();
+ }
+
+ @Override
+ public boolean isAdminSession(HttpServletRequest request) {
+ return Boolean.TRUE.equals(request.getSession().getAttribute(
+ ADMIN_SESSION_ATTRIBUTE));
+ }
+
+ @Override
+ public String getRealm(HttpServletRequest request) {
+ return getOAuthRealm();
+ }
+
+ @Override
+ public boolean isAuthenticated(HttpServletRequest request) {
+ @SuppressWarnings("unchecked")
+ Connection connector = (Connection) request.getSession().getAttribute(CONNECTOR_ATTRIBUTE);
+ if (connector == null) {
+ return false;
+ }
+ request.setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ return true;
+ }
+ });
+
+ /*
+ * Override some SimpleTokenStrategy methods so that we can keep the
+ * Connector associated with the OAuth tokens.
+ */
+ config.setTokenStrategy(new SimpleTokenStrategy() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public void markRequestTokenAuthorized(
+ HttpServletRequest httpRequest, String requestToken)
+ throws OAuthProblemException {
+ keyToConnectorCache.put(requestToken,
+ (Connection) httpRequest.getAttribute(CONNECTOR_ATTRIBUTE));
+ super.markRequestTokenAuthorized(httpRequest, requestToken);
+ }
+
+ @Override
+ public void generateAccessToken(OAuthRequest oAuthRequest)
+ throws OAuthProblemException, IOException {
+ String requestToken = oAuthRequest.getMessage().getToken();
+ Connection bc = keyToConnectorCache.remove(requestToken);
+ super.generateAccessToken(oAuthRequest);
+ keyToConnectorCache.put(oAuthRequest.getAccessor().accessToken, bc);
+ }
+ });
+
+ try {
+ // For now, hard-code the consumers.
+ config.setConsumerStore(createConsumerStore());
+ } catch (Throwable t) {
+ System.err.println("Error initializing the OAuth consumer store: " + t.getMessage());
+ }
+ }
+
+ /**
+ * Jazz requires a exception with the magic string "invalid_expired_token" to restart
+ * OAuth authentication
+ * @param e
+ * @return
+ * @throws OAuthProblemException
+ */
+ private void throwInvalidExpiredException(OAuthProblemException e) throws OAuthProblemException {
+ OAuthProblemException ope = new OAuthProblemException(JAZZ_INVALID_EXPIRED_TOKEN_OAUTH_PROBLEM);
+ ope.setParameter(HttpMessage.STATUS_CODE, new Integer(
+ HttpServletResponse.SC_UNAUTHORIZED));
+ throw ope;
+ }
+
+ private void sendUnauthorizedResponse(HttpServletResponse response,
+ UnauthorizedException e) throws IOException, ServletException {
+ // Accept basic access or OAuth authentication.
+ final String WWW_AUTHENTICATE_HEADER = "WWW-Authenticate";
+ final String BASIC_AUTHORIZATION_PREFIX = "Basic ";
+ final String BASIC_AUTHENTICATION_CHALLENGE = BASIC_AUTHORIZATION_PREFIX
+ + "realm=\"" + getOAuthRealm() + "\"";
+ final String OAUTH_AUTHORIZATION_PREFIX = "OAuth ";
+ final String OAUTH_AUTHENTICATION_CHALLENGE = OAUTH_AUTHORIZATION_PREFIX
+ + "realm=\"" + getOAuthRealm() + "\"";
+
+ response.addHeader(WWW_AUTHENTICATE_HEADER,
+ OAUTH_AUTHENTICATION_CHALLENGE);
+ response.addHeader(WWW_AUTHENTICATE_HEADER,
+ BASIC_AUTHENTICATION_CHALLENGE);
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/BugzillaAdapterCredentialsFilter.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/BugzillaAdapterCredentialsFilter.java
new file mode 100644
index 0000000..86ac1b4
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/BugzillaAdapterCredentialsFilter.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Michael Fiedler - initial API and implementation for Bugzilla adapter
+ *
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.eclipse.lyo.oslc4j.bugzilla.BugzillaManager;
+import org.eclipse.lyo.oslc4j.bugzilla.Credentials;
+import org.eclipse.lyo.oslc4j.bugzilla.exception.UnauthorizedException;
+import org.eclipse.lyo.oslc4j.bugzilla.utils.HttpUtils;
+import org.eclipse.lyo.server.oauth.consumerstore.FileSystemConsumerStore;
+import org.eclipse.lyo.server.oauth.core.consumer.ConsumerStore;
+
+import com.j2bugzilla.base.BugzillaConnector;
+import com.j2bugzilla.base.BugzillaException;
+import com.j2bugzilla.base.ConnectionException;
+import com.j2bugzilla.rpc.LogIn;
+
+/**
+ * This is yet another {@link CredentialsFilter} that is based on the common base class.
+ * The base class provide common technique to implement both HTTP Basic and OAuth for
+ * your adapter. You concentrate in this class implementing login method to your tool.
+ *
+ * <p>You can try this CredentialsFilter by replacing all occurences of CredentialsFilter
+ * in this Bugzilla TRS adapter example. They are in {@link BugzillaManager} and
+ * web.xml.
+ *
+ * @see AbstractAdapterCredentialsFilter
+ */
+public class BugzillaAdapterCredentialsFilter
+ extends AbstractAdapterCredentialsFilter<Credentials, BugzillaConnector> {
+
+ public BugzillaAdapterCredentialsFilter()
+ {
+ super("Bugzilla", "Bugzilla"); // Initialize superclass with the display name and realm.
+ }
+
+ @Override
+ protected Credentials getCredentialsForOAuth(String id, String password) {
+ if (id == OAUTH_EMPTY_TOKEN_KEY) {
+ return BugzillaManager.getAdminCredentials();
+ }
+ Credentials result = new Credentials();
+ result.setUsername(id);
+ result.setPassword(password);
+ return result;
+ }
+
+ @Override
+ protected Credentials getCredentialsFromRequest(HttpServletRequest request) throws UnauthorizedException {
+ Credentials credentials = HttpUtils.getCredentials(request);
+ if (credentials == null) {
+ throw new UnauthorizedException();
+ }
+ return credentials;
+ }
+
+ @Override
+ protected BugzillaConnector login(Credentials creds, HttpServletRequest request)
+ throws UnauthorizedException, ServletException
+ {
+ BugzillaConnector bc = new BugzillaConnector();
+ try {
+ bc.connectTo(BugzillaManager.getBugzillaUri() + "/xmlrpc.cgi");
+ } catch (ConnectionException e) {
+ throw new ServletException(e);
+ }
+
+ LogIn login = new LogIn(creds.getUsername(), creds.getPassword());
+ try {
+ bc.executeMethod(login);
+ } catch (BugzillaException e) {
+ e.printStackTrace();
+ throw new UnauthorizedException(e.getCause().getMessage());
+ }
+ return bc;
+ }
+
+ @Override
+ protected void logout(BugzillaConnector loginSession, HttpSession session)
+ {
+ // do nothing for Bugzilla
+ }
+
+ @Override
+ protected boolean isAdminSession(String id, BugzillaConnector session,
+ HttpServletRequest request)
+ {
+ String admin = BugzillaManager.getAdmin();
+ return admin != null && admin.equals(id);
+ }
+
+ @Override
+ protected ConsumerStore createConsumerStore() throws Exception
+ {
+ return new FileSystemConsumerStore("bugzillaOAuthStore.xml");
+ }
+
+ @Override
+ protected void doChainDoFilterWithConnector(HttpServletRequest request,
+ HttpServletResponse response, FilterChain chain,
+ BugzillaConnector connector) throws IOException, ServletException {
+
+ //
+ // As BugzillaConnector doesn't support concurrent access, serialize the
+ // request processes here to avoid concurrent access.
+ //
+ synchronized (connector) {
+ request.setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ chain.doFilter(request, response);
+ }
+ }
+
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/BugzillaAdapterCredentialsFilterMT.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/BugzillaAdapterCredentialsFilterMT.java
new file mode 100644
index 0000000..389efe5
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/BugzillaAdapterCredentialsFilterMT.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Michael Fiedler - initial API and implementation for Bugzilla adapter
+ *
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.servlet;
+
+import java.io.IOException;
+import java.util.WeakHashMap;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.lyo.oslc4j.bugzilla.BugzillaManager;
+import org.eclipse.lyo.oslc4j.bugzilla.Credentials;
+import org.eclipse.lyo.oslc4j.bugzilla.exception.UnauthorizedException;
+
+import com.j2bugzilla.base.BugzillaConnector;
+import com.j2bugzilla.base.BugzillaException;
+import com.j2bugzilla.base.ConnectionException;
+import com.j2bugzilla.rpc.LogIn;
+
+/**
+ * Concurrent access support
+ *
+ * <p>This class keeps {@link #connectorPoolMap} map between an instance of BugzillaConnector, which represents a login session (we
+ * call this as "session instance" here for after), and
+ * available instances of the BugzillaConnectors built for the session. The shape of
+ * the map is illustrated bellow:
+ * <pre>{[BugzillaConnector at login] =&lt; [QUEUE: [BugzillaConnector at login],[BugzillaConnector],..]}</pre>
+ *
+ * Note that the session instance is also in the queue.
+ *
+ * <p>Client takes the instance using {@link #acquireConnector(BugzillaConnector)} and release
+ * by {@link #releaseConnector(BugzillaConnector, BugzillaConnector)}.
+ *
+ * @see #buildConnectorPool(BugzillaConnector, Credentials)
+ * @see #acquireConnector(BugzillaConnector)
+ * @see #releaseConnector(BugzillaConnector, BugzillaConnector)
+ */
+public class BugzillaAdapterCredentialsFilterMT
+ extends BugzillaAdapterCredentialsFilter {
+
+ /**
+ * The number of allowed concurrent bugzilla connector threads for each session
+ */
+ private final int MAX_CONCURRENT_THREADS = 2;
+
+ /**
+ */
+ private WeakHashMap<BugzillaConnector, BlockingQueue<BugzillaConnector>> connectorPoolMap = new WeakHashMap<BugzillaConnector, BlockingQueue<BugzillaConnector>>();
+
+ public BugzillaAdapterCredentialsFilterMT()
+ {
+ super();
+ }
+
+ @Override
+ protected BugzillaConnector login(Credentials creds, HttpServletRequest request)
+ throws UnauthorizedException, ServletException
+ {
+ BugzillaConnector keyConnector = super.login(creds, request);
+ buildConnectorPool(keyConnector, creds);
+ return keyConnector;
+ }
+
+ private BugzillaConnector doLogin(Credentials creds)
+ throws ServletException, UnauthorizedException {
+ BugzillaConnector bc = new BugzillaConnector();
+ try {
+ bc.connectTo(BugzillaManager.getBugzillaUri() + "/xmlrpc.cgi");
+ } catch (ConnectionException e) {
+ throw new ServletException(e);
+ }
+
+ LogIn login = new LogIn(creds.getUsername(), creds.getPassword());
+ try {
+ bc.executeMethod(login);
+ } catch (BugzillaException e) {
+ e.printStackTrace();
+ throw new UnauthorizedException(e.getCause().getMessage());
+ }
+ return bc;
+ }
+
+ @Override
+ protected void doChainDoFilterWithConnector(HttpServletRequest request,
+ HttpServletResponse response, FilterChain chain,
+ BugzillaConnector connector) throws IOException, ServletException {
+
+ BugzillaConnector requestConnector = acquireConnector(connector);
+ try {
+ //super.doChainDoFilterWithConnector(request, response, chain, requestConnector);
+ request.setAttribute(CONNECTOR_ATTRIBUTE, requestConnector);
+ chain.doFilter(request, response);
+ } finally {
+ releaseConnector(connector, requestConnector);
+ }
+ }
+
+ /**
+ * Prepare connection pool with two connections available for the current login
+ */
+ private void buildConnectorPool(BugzillaConnector keyConnector, Credentials creds) throws ServletException {
+ BlockingQueue<BugzillaConnector> queue = new ArrayBlockingQueue<BugzillaConnector>(MAX_CONCURRENT_THREADS);
+ queue.add(keyConnector);
+ for (int i=1; i<MAX_CONCURRENT_THREADS; i++) {
+ BugzillaConnector con;
+ try {
+ con = doLogin(creds);
+ queue.add(con);
+ } catch (UnauthorizedException e) {
+ throw new ServletException(e);
+ }
+ }
+ connectorPoolMap.put(keyConnector, queue);
+ }
+
+ private BugzillaConnector acquireConnector(BugzillaConnector keyConnector) throws ServletException {
+ try {
+ return connectorPoolMap.get(keyConnector).take();
+ } catch (InterruptedException e) {
+ throw new ServletException(e);
+ }
+ }
+
+ private void releaseConnector(BugzillaConnector keyConnector,
+ BugzillaConnector requestConnector) throws ServletException {
+ try {
+ connectorPoolMap.get(keyConnector).put(requestConnector);
+ } catch (InterruptedException e) {
+ throw new ServletException(e);
+ }
+ }
+
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/BugzillaServiceProviderFactory.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/BugzillaServiceProviderFactory.java
new file mode 100644
index 0000000..0005843
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/BugzillaServiceProviderFactory.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Russell Boykin - initial API and implementation
+ * Alberto Giammaria - initial API and implementation
+ * Chris Peters - initial API and implementation
+ * Gianluca Bernardini - initial API and implementation
+ * Michael Fiedler - Bugzilla adapter implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.servlet;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Map;
+
+import org.eclipse.lyo.core.trs.TRSConstants;
+import org.eclipse.lyo.oslc4j.bugzilla.Constants;
+import org.eclipse.lyo.oslc4j.bugzilla.services.BugzillaChangeRequestService;
+import org.eclipse.lyo.oslc4j.client.ServiceProviderRegistryURIs;
+import org.eclipse.lyo.oslc4j.core.exception.OslcCoreApplicationException;
+import org.eclipse.lyo.oslc4j.core.model.OslcConstants;
+import org.eclipse.lyo.oslc4j.core.model.PrefixDefinition;
+import org.eclipse.lyo.oslc4j.core.model.Publisher;
+import org.eclipse.lyo.oslc4j.core.model.ServiceProvider;
+import org.eclipse.lyo.oslc4j.core.model.ServiceProviderFactory;
+
+public class BugzillaServiceProviderFactory
+{
+ private static Class<?>[] RESOURCE_CLASSES =
+ {
+ BugzillaChangeRequestService.class
+ };
+
+ private BugzillaServiceProviderFactory()
+ {
+ super();
+ }
+
+ /**
+ * Create a new Bugzilla OSLC change management service provider.
+ * @param baseURI
+ * @param product
+ * @param parameterValueMap - a map containing the path replacement value for {productId}. See ServiceProviderCatalogSingleton.initServiceProvidersFromProducts()
+ * @return
+ * @throws OslcCoreApplicationException
+ * @throws URISyntaxException
+ */
+ public static ServiceProvider createServiceProvider(final String baseURI, final String product, final Map<String,Object> parameterValueMap)
+ throws OslcCoreApplicationException, URISyntaxException
+ {
+ final ServiceProvider serviceProvider = ServiceProviderFactory.createServiceProvider(baseURI,
+ ServiceProviderRegistryURIs.getUIURI(),
+ product,
+ "Service provider for Bugzilla product: "+product,
+ new Publisher("Eclipse Lyo", "urn:oslc:ServiceProvider"),
+ RESOURCE_CLASSES,
+ parameterValueMap);
+ URI detailsURIs[] = {new URI(baseURI + "/details")};
+ serviceProvider.setDetails(detailsURIs);
+
+ final PrefixDefinition[] prefixDefinitions =
+ {
+ new PrefixDefinition(OslcConstants.DCTERMS_NAMESPACE_PREFIX, new URI(OslcConstants.DCTERMS_NAMESPACE)),
+ new PrefixDefinition(OslcConstants.OSLC_CORE_NAMESPACE_PREFIX, new URI(OslcConstants.OSLC_CORE_NAMESPACE)),
+ new PrefixDefinition(OslcConstants.OSLC_DATA_NAMESPACE_PREFIX, new URI(OslcConstants.OSLC_DATA_NAMESPACE)),
+ new PrefixDefinition(OslcConstants.RDF_NAMESPACE_PREFIX, new URI(OslcConstants.RDF_NAMESPACE)),
+ new PrefixDefinition(OslcConstants.RDFS_NAMESPACE_PREFIX, new URI(OslcConstants.RDFS_NAMESPACE)),
+ new PrefixDefinition(Constants.CHANGE_MANAGEMENT_NAMESPACE_PREFIX, new URI(Constants.CHANGE_MANAGEMENT_NAMESPACE)),
+ new PrefixDefinition(Constants.BUGZILLA_NAMESPACE_PREFIX, new URI(Constants.BUGZILLA_NAMESPACE)),
+ new PrefixDefinition(Constants.FOAF_NAMESPACE_PREFIX, new URI(Constants.FOAF_NAMESPACE)),
+ new PrefixDefinition(Constants.QUALITY_MANAGEMENT_PREFIX, new URI(Constants.QUALITY_MANAGEMENT_NAMESPACE)),
+ new PrefixDefinition(Constants.REQUIREMENTS_MANAGEMENT_PREFIX, new URI(Constants.REQUIREMENTS_MANAGEMENT_NAMESPACE)),
+ new PrefixDefinition(Constants.SOFTWARE_CONFIGURATION_MANAGEMENT_PREFIX, new URI(Constants.SOFTWARE_CONFIGURATION_MANAGEMENT_NAMESPACE)),
+ // Added in Lab 1.3
+ new PrefixDefinition(TRSConstants.TRS_NAMESPACE_PREFIX, new URI(TRSConstants.TRS_NAMESPACE))
+ };
+
+ serviceProvider.setPrefixDefinitions(prefixDefinitions);
+
+ return serviceProvider;
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/CredentialsFilter.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/CredentialsFilter.java
new file mode 100644
index 0000000..ed614a2
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/CredentialsFilter.java
@@ -0,0 +1,360 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Michael Fiedler - initial API and implementation for Bugzilla adapter
+ *
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.servlet;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import net.oauth.OAuth;
+import net.oauth.OAuthAccessor;
+import net.oauth.OAuthException;
+import net.oauth.OAuthMessage;
+import net.oauth.OAuthProblemException;
+import net.oauth.http.HttpMessage;
+import net.oauth.server.OAuthServlet;
+
+import org.eclipse.lyo.oslc4j.bugzilla.BugzillaManager;
+import org.eclipse.lyo.oslc4j.bugzilla.Credentials;
+import org.eclipse.lyo.oslc4j.bugzilla.exception.UnauthorizedException;
+import org.eclipse.lyo.oslc4j.bugzilla.utils.HttpUtils;
+import org.eclipse.lyo.server.oauth.consumerstore.FileSystemConsumerStore;
+import org.eclipse.lyo.server.oauth.core.Application;
+import org.eclipse.lyo.server.oauth.core.AuthenticationException;
+import org.eclipse.lyo.server.oauth.core.OAuthConfiguration;
+import org.eclipse.lyo.server.oauth.core.OAuthRequest;
+import org.eclipse.lyo.server.oauth.core.consumer.LyoOAuthConsumer;
+import org.eclipse.lyo.server.oauth.core.token.LRUCache;
+import org.eclipse.lyo.server.oauth.core.token.SimpleTokenStrategy;
+
+import com.j2bugzilla.base.BugzillaConnector;
+import com.j2bugzilla.base.BugzillaException;
+import com.j2bugzilla.base.ConnectionException;
+import com.j2bugzilla.rpc.LogIn;
+
+public class CredentialsFilter implements Filter {
+
+
+
+ public static final String CONNECTOR_ATTRIBUTE = BugzillaAdapterCredentialsFilter.CONNECTOR_ATTRIBUTE;
+ public static final String CREDENTIALS_ATTRIBUTE = BugzillaAdapterCredentialsFilter.CREDENTIALS_ATTRIBUTE;
+ private static final String ADMIN_SESSION_ATTRIBUTE = BugzillaAdapterCredentialsFilter.ADMIN_SESSION_ATTRIBUTE;
+ public static final String JAZZ_INVALID_EXPIRED_TOKEN_OAUTH_PROBLEM = BugzillaAdapterCredentialsFilter.JAZZ_INVALID_EXPIRED_TOKEN_OAUTH_PROBLEM;
+ public static final String OAUTH_REALM = "Bugzilla";
+
+ private static LRUCache<String, BugzillaConnector> keyToConnectorCache = new LRUCache<String, BugzillaConnector>(200);
+
+ @Override
+ public void destroy() {
+
+
+ }
+
+
+ /*
+ * Modified in Lab 1.2
+ */
+ /**
+ * Check for OAuth or BasicAuth credentials and challenge if not found.
+ *
+ * Store the BugzillaConnector in the HttpSession for retrieval in the REST services.
+ */
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+ FilterChain chain) throws IOException, ServletException {
+
+ if(servletRequest instanceof HttpServletRequest && servletResponse instanceof HttpServletResponse) {
+ HttpServletRequest request = (HttpServletRequest) servletRequest;
+ HttpServletResponse response = (HttpServletResponse) servletResponse;
+
+ boolean isTwoLeggedOAuthRequest = false;
+
+ //Don't protect requests to oauth service. TODO: possibly do this in web.xml
+ if (! request.getPathInfo().startsWith("/oauth"))
+ {
+
+ // First check if this is an OAuth request.
+ try {
+ try {
+ OAuthMessage message = OAuthServlet.getMessage(request, null);
+ // test if this is a valid two-legged oauth request
+ if ("".equals(message.getToken())) {
+ validateTwoLeggedOAuthMessage(message);
+ isTwoLeggedOAuthRequest = true;
+ }
+
+ if (!isTwoLeggedOAuthRequest && message.getToken() != null) {
+ OAuthRequest oAuthRequest = new OAuthRequest(request);
+ oAuthRequest.validate();
+ BugzillaConnector connector = keyToConnectorCache.get(message
+ .getToken());
+ if (connector == null) {
+ throw new OAuthProblemException(
+ OAuth.Problems.TOKEN_REJECTED);
+ }
+
+ request.getSession().setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ }
+ } catch (OAuthProblemException e) {
+ if (OAuth.Problems.TOKEN_REJECTED.equals(e.getProblem()))
+ throwInvalidExpiredException(e);
+ else
+ throw e;
+ }
+ } catch (OAuthException e) {
+ OAuthServlet.handleException(response, e, OAUTH_REALM);
+ return;
+ } catch (URISyntaxException e) {
+ throw new ServletException(e);
+ }
+
+
+ // This is not an OAuth request. Check for basic access authentication.
+ HttpSession session = request.getSession();
+ BugzillaConnector connector = (BugzillaConnector) session
+ .getAttribute(CONNECTOR_ATTRIBUTE);
+ if (connector == null) {
+ try {
+ Credentials credentials;
+ if (isTwoLeggedOAuthRequest) {
+ connector = keyToConnectorCache.get("");
+ if (connector == null) {
+ credentials = BugzillaManager.getAdminCredentials();
+ connector = getBugzillaConnector(credentials);
+ keyToConnectorCache.put("", connector);
+ }
+ credentials = null; // TODO; Do we need to keep the credentials for this path ??
+ } else {
+ credentials = (Credentials) request.getSession().getAttribute(CREDENTIALS_ATTRIBUTE);
+ if (credentials == null)
+ {
+ credentials = HttpUtils.getCredentials(request);
+ if (credentials == null) {
+ throw new UnauthorizedException();
+ }
+ }
+ connector = getBugzillaConnector(credentials);
+ }
+ session.setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ session.setAttribute(CREDENTIALS_ATTRIBUTE,
+ credentials);
+
+ } catch (UnauthorizedException e)
+ {
+ HttpUtils.sendUnauthorizedResponse(response, e);
+ System.err.println(e.getMessage());
+ return;
+ } catch (ConnectionException ce)
+ {
+ throw new ServletException(ce);
+ }
+
+ }
+
+ // Lock Bugzilla connector instance to prevent concurrent access
+ if (connector != null) {
+ synchronized (connector) {
+ servletRequest.setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ chain.doFilter(servletRequest, servletResponse);
+ }
+ return;
+ }
+ }
+ }
+
+ chain.doFilter(servletRequest, servletResponse);
+ }
+
+ /*
+ * Added in Lab 1.2
+ */
+ private void validateTwoLeggedOAuthMessage(OAuthMessage message)
+ throws IOException, OAuthException,
+ URISyntaxException {
+ OAuthConfiguration config = OAuthConfiguration.getInstance();
+ LyoOAuthConsumer consumer = config.getConsumerStore().getConsumer(message.getConsumerKey());
+ if (consumer != null && consumer.isTrusted()) {
+ // The request can be a two-legged oauth request because it's a trusted consumer
+ // Validate the message with an empty token and an empty secret
+ OAuthAccessor accessor = new OAuthAccessor(consumer);
+ accessor.requestToken = "";
+ accessor.tokenSecret = "";
+ config.getValidator().validateMessage(message, accessor);
+ } else {
+ throw new OAuthProblemException(
+ OAuth.Problems.TOKEN_REJECTED);
+ }
+ }
+
+ public static BugzillaConnector getBugzillaConnector(Credentials credentials)
+ throws ConnectionException, UnauthorizedException {
+ BugzillaConnector bc = new BugzillaConnector();
+ bc.connectTo(BugzillaManager.getBugzillaUri() + "/xmlrpc.cgi");
+ LogIn login = new LogIn(credentials.getUsername(), credentials.getPassword());
+ try {
+ bc.executeMethod(login);
+ } catch (BugzillaException e) {
+ e.printStackTrace();
+ throw new UnauthorizedException(e.getCause().getMessage());
+ }
+ return bc;
+ }
+
+ @Override
+ public void init(FilterConfig arg0) throws ServletException {
+ OAuthConfiguration config = OAuthConfiguration.getInstance();
+
+ // Validates a user's ID and password.
+ config.setApplication(new Application() {
+ @Override
+ public void login(HttpServletRequest request, String id,
+ String password) throws AuthenticationException {
+ try {
+ BugzillaConnector bc = new BugzillaConnector();
+ bc.connectTo(BugzillaManager.getBugzillaUri() + "/xmlrpc.cgi");
+ LogIn login = new LogIn(id, password);
+ bc.executeMethod(login);
+ request.setAttribute(CONNECTOR_ATTRIBUTE, bc);
+ String admin = BugzillaManager.getAdmin();
+ request.getSession().setAttribute(ADMIN_SESSION_ATTRIBUTE,
+ admin != null && admin.equals(id));
+ Credentials creds = new Credentials();
+ creds.setUsername(id);
+ creds.setPassword(password);
+ request.getSession().setAttribute(CREDENTIALS_ATTRIBUTE,
+ creds);
+ // Added in Lab 1.2
+ request.getSession().setAttribute(CONNECTOR_ATTRIBUTE, bc);
+ } catch (Exception e) {
+ throw new AuthenticationException(e.getCause().getMessage(), e);
+ }
+ }
+
+ @Override
+ public String getName() {
+ // Display name for this application.
+ return "Bugzilla";
+ }
+
+ @Override
+ public boolean isAdminSession(HttpServletRequest request) {
+ return Boolean.TRUE.equals(request.getSession().getAttribute(
+ ADMIN_SESSION_ATTRIBUTE));
+ }
+
+ @Override
+ public String getRealm(HttpServletRequest request) {
+ return BugzillaManager.REALM;
+ }
+
+ @Override
+ public boolean isAuthenticated(HttpServletRequest request) {
+ BugzillaConnector bc = (BugzillaConnector) request.getSession()
+ .getAttribute(CONNECTOR_ATTRIBUTE);
+ if (bc == null) {
+ return false;
+ }
+
+ request.setAttribute(CONNECTOR_ATTRIBUTE, bc);
+ return true;
+ }
+ });
+
+ /*
+ * Override some SimpleTokenStrategy methods so that we can keep the
+ * BugzillaConnection associated with the OAuth tokens.
+ */
+ config.setTokenStrategy(new SimpleTokenStrategy() {
+ @Override
+ public void markRequestTokenAuthorized(
+ HttpServletRequest httpRequest, String requestToken)
+ throws OAuthProblemException {
+ keyToConnectorCache.put(requestToken,
+ (BugzillaConnector) httpRequest.getAttribute(CONNECTOR_ATTRIBUTE));
+ super.markRequestTokenAuthorized(httpRequest, requestToken);
+ }
+
+ @Override
+ public void generateAccessToken(OAuthRequest oAuthRequest)
+ throws OAuthProblemException, IOException {
+ String requestToken = oAuthRequest.getMessage().getToken();
+ BugzillaConnector bc = keyToConnectorCache.remove(requestToken);
+ super.generateAccessToken(oAuthRequest);
+ keyToConnectorCache.put(oAuthRequest.getAccessor().accessToken, bc);
+ }
+ });
+
+ try {
+ // For now, hard-code the consumers.
+ config.setConsumerStore(new FileSystemConsumerStore("bugzillaOAuthStore.xml"));
+ } catch (Throwable t) {
+ System.err.println("Error initializing the OAuth consumer store: " + t.getMessage());
+
+ }
+
+ }
+
+ /**
+ * Jazz requires a exception with the magic string "invalid_expired_token" to restart
+ * OAuth authentication
+ * @param e
+ * @return
+ * @throws OAuthProblemException
+ */
+ private void throwInvalidExpiredException(OAuthProblemException e) throws OAuthProblemException {
+ OAuthProblemException ope = new OAuthProblemException(JAZZ_INVALID_EXPIRED_TOKEN_OAUTH_PROBLEM);
+ ope.setParameter(HttpMessage.STATUS_CODE, new Integer(
+ HttpServletResponse.SC_UNAUTHORIZED));
+ throw ope;
+ }
+
+ /**
+ * Get BugzillaConnector
+ * @param request
+ * @return
+ */
+ public static BugzillaConnector getConnector(HttpServletRequest request)
+ {
+ //connector should never be null if CredentialsFilter is doing its job
+ @SuppressWarnings("unchecked")
+ BugzillaConnector connector = (BugzillaConnector) request.getAttribute(CONNECTOR_ATTRIBUTE);
+ return connector;
+ }
+
+ /**
+ * Get Credentials for this session
+ * @param request
+ * @return credentials
+ */
+ public static Credentials getCredentials(HttpServletRequest request)
+ {
+ @SuppressWarnings("unchecked")
+ Credentials credentials = (Credentials) request.getSession().getAttribute(CREDENTIALS_ATTRIBUTE);
+ return credentials;
+ }
+
+
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/ServiceProviderCatalogSingleton.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/ServiceProviderCatalogSingleton.java
new file mode 100644
index 0000000..f7b8059
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/servlet/ServiceProviderCatalogSingleton.java
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Russell Boykin - initial API and implementation
+ * Alberto Giammaria - initial API and implementation
+ * Chris Peters - initial API and implementation
+ * Gianluca Bernardini - initial API and implementation
+ * Michael Fiedler - adapted for Bugzilla service provider
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.servlet;
+
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.lyo.oslc4j.bugzilla.BugzillaManager;
+import org.eclipse.lyo.oslc4j.bugzilla.jbugzx.rpc.GetAccessibleProducts;
+import org.eclipse.lyo.oslc4j.client.ServiceProviderRegistryURIs;
+import org.eclipse.lyo.oslc4j.core.model.Publisher;
+import org.eclipse.lyo.oslc4j.core.model.Service;
+import org.eclipse.lyo.oslc4j.core.model.ServiceProvider;
+import org.eclipse.lyo.oslc4j.core.model.ServiceProviderCatalog;
+
+import com.j2bugzilla.base.BugzillaConnector;
+import com.j2bugzilla.rpc.GetProduct;
+
+/**
+ * This is the OSLC service provider catalog for the Bugzilla adapter. Service providers are
+ * not registered with the catalog until a request comes in to access either the catalog or a
+ * specific service provider. This request could be from an external consumer or an internal
+ * request triggered by a consumer accessing a change request.
+ *
+ * The service providers are created and registered in the initServiceProvidersFromProducts()
+ * method. A list of accessible products is retrieved from Bugzilla and a ServiceProvider is
+ * created and registered for each using the Bugzilla productId as the identifier.
+ *
+ * The registered service providers are refreshed on each catalog or service provider collection
+ * request.
+ */
+public class ServiceProviderCatalogSingleton
+{
+ private static final ServiceProviderCatalog serviceProviderCatalog;
+ private static final SortedMap<String, ServiceProvider> serviceProviders = new TreeMap<String, ServiceProvider>();
+
+ static
+ {
+ try
+ {
+ serviceProviderCatalog = new ServiceProviderCatalog();
+
+ serviceProviderCatalog.setAbout(new URI(ServiceProviderRegistryURIs.getServiceProviderRegistryURI()));
+ serviceProviderCatalog.setTitle("OSLC Service Provider Catalog");
+ serviceProviderCatalog.setDescription("OSLC Service Provider Catalog");
+ serviceProviderCatalog.setPublisher(new Publisher("Project Lyo", "org.eclipse.lyo.oslc4j.bugzilla"));
+ serviceProviderCatalog.getPublisher().setIcon(new URI("http://open-services.net/css/images/logo-forflip.png"));
+ }
+ catch (final URISyntaxException exception)
+ {
+ // We should never get here.
+ throw new ExceptionInInitializerError(exception);
+ }
+ }
+
+
+ private ServiceProviderCatalogSingleton()
+ {
+ super();
+ }
+
+
+ public static URI getUri()
+ {
+ return serviceProviderCatalog.getAbout();
+ }
+
+ public static ServiceProviderCatalog getServiceProviderCatalog(HttpServletRequest httpServletRequest)
+ {
+ initServiceProvidersFromProducts(httpServletRequest);
+ return serviceProviderCatalog;
+ }
+
+ public static ServiceProvider[] getServiceProviders(HttpServletRequest httpServletRequest)
+ {
+ synchronized(serviceProviders)
+ {
+ initServiceProvidersFromProducts(httpServletRequest);
+ return serviceProviders.values().toArray(new ServiceProvider[serviceProviders.size()]);
+ }
+ }
+
+ public static ServiceProvider getServiceProvider(HttpServletRequest httpServletRequest, final String serviceProviderId)
+ {
+ ServiceProvider serviceProvider;
+
+ synchronized(serviceProviders)
+ {
+ serviceProvider = serviceProviders.get(serviceProviderId);
+
+ //One retry refreshing the service providers
+ if (serviceProvider == null)
+ {
+ getServiceProviders(httpServletRequest);
+ serviceProvider = serviceProviders.get(serviceProviderId);
+ }
+ }
+
+ if (serviceProvider != null)
+ {
+ return serviceProvider;
+ }
+
+ throw new WebApplicationException(Status.NOT_FOUND);
+ }
+
+ public static ServiceProvider registerServiceProvider(final HttpServletRequest httpServletRequest,
+ final ServiceProvider serviceProvider,
+ final String productId) throws URISyntaxException
+ {
+ synchronized(serviceProviders)
+ {
+ final URI serviceProviderURI = new URI(httpServletRequest.getScheme(),
+ null,
+ httpServletRequest.getServerName(),
+ httpServletRequest.getServerPort(),
+ httpServletRequest.getContextPath() + "/serviceProviders/" + productId,
+ null,
+ null);
+
+ return registerServiceProviderNoSync(serviceProviderURI,
+ serviceProvider,
+ productId);
+ }
+ }
+
+
+/**
+ * Register a service provider with the OSLC catalog
+ *
+ * @param serviceProviderURI
+ * @param serviceProvider
+ * @param productId
+ * @return
+ */
+ private static ServiceProvider registerServiceProviderNoSync(final URI serviceProviderURI,
+ final ServiceProvider serviceProvider,
+ final String productId)
+ {
+ final SortedSet<URI> serviceProviderDomains = getServiceProviderDomains(serviceProvider);
+
+ serviceProvider.setAbout(serviceProviderURI);
+ serviceProvider.setIdentifier(productId);
+ serviceProvider.setCreated(new Date());
+
+ serviceProviderCatalog.addServiceProvider(serviceProvider);
+ serviceProviderCatalog.addDomains(serviceProviderDomains);
+
+ serviceProviders.put(productId,
+ serviceProvider);
+
+
+ return serviceProvider;
+ }
+
+ // This version is for self-registration and thus package-protected
+ static ServiceProvider registerServiceProvider(final String baseURI,
+ final ServiceProvider serviceProvider,
+ final String productId)
+ throws URISyntaxException
+ {
+ synchronized(serviceProviders)
+ {
+ final URI serviceProviderURI = new URI(baseURI + "/serviceProviders/" + productId);
+
+ return registerServiceProviderNoSync(serviceProviderURI,
+ serviceProvider,
+ productId);
+ }
+ }
+
+ public static void deregisterServiceProvider(final String serviceProviderId)
+ {
+ synchronized(serviceProviders)
+ {
+ final ServiceProvider deregisteredServiceProvider = serviceProviders.remove(serviceProviderId);
+
+ if (deregisteredServiceProvider != null)
+ {
+ final SortedSet<URI> remainingDomains = new TreeSet<URI>();
+
+ for (final ServiceProvider remainingServiceProvider : serviceProviders.values())
+ {
+ remainingDomains.addAll(getServiceProviderDomains(remainingServiceProvider));
+ }
+
+ final SortedSet<URI> removedServiceProviderDomains = getServiceProviderDomains(deregisteredServiceProvider);
+
+ removedServiceProviderDomains.removeAll(remainingDomains);
+ serviceProviderCatalog.removeDomains(removedServiceProviderDomains);
+ serviceProviderCatalog.removeServiceProvider(deregisteredServiceProvider);
+ }
+ else
+ {
+ throw new WebApplicationException(Status.NOT_FOUND);
+ }
+ }
+ }
+
+ private static SortedSet<URI> getServiceProviderDomains(final ServiceProvider serviceProvider)
+ {
+ final SortedSet<URI> domains = new TreeSet<URI>();
+
+ if (serviceProvider!=null) {
+ final Service[] services = serviceProvider.getServices();
+ for (final Service service : services)
+ {
+ final URI domain = service.getDomain();
+
+ domains.add(domain);
+ }
+ }
+ return domains;
+ }
+
+ /**
+ * Retrieve a list of products from Bugzilla and construct a service provider for each.
+ *
+ * Each product ID is added to the parameter map which will be used during service provider
+ * creation to create unique URI paths for each Bugzilla product. See @Path definition at
+ * the top of BugzillaChangeRequestService.
+ *
+ * @param httpServletRequest
+ */
+ protected static void initServiceProvidersFromProducts (HttpServletRequest httpServletRequest)
+ {
+
+ try {
+ BugzillaConnector bc = BugzillaManager.getBugzillaConnector(httpServletRequest);
+
+ GetAccessibleProducts getProductIds = new GetAccessibleProducts();
+ if (bc != null)
+ {
+ bc.executeMethod(getProductIds);
+ Integer[] productIds = getProductIds.getIds();
+
+ String basePath = BugzillaManager.getBugzServiceBase();
+
+ for (Integer p : productIds) {
+ String productId = Integer.toString(p);
+
+ if (! serviceProviders.containsKey(productId)) {
+
+ GetProduct getProductMethod = new GetProduct(p);
+ bc.executeMethod(getProductMethod);
+ String product = getProductMethod.getProduct().getName();
+
+
+ Map<String, Object> parameterMap = new HashMap<String, Object>();
+ parameterMap.put("productId",productId);
+ final ServiceProvider bugzillaServiceProvider = BugzillaServiceProviderFactory.createServiceProvider(basePath, product, parameterMap);
+ registerServiceProvider(basePath,bugzillaServiceProvider,productId);
+ }
+ }
+ } else {
+ System.err.println("Bugzilla Connectorn not initialized - check bugz.properties");
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new WebApplicationException(e,Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/BugSearch2.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/BugSearch2.java
new file mode 100644
index 0000000..9cf5e69
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/BugSearch2.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * * Contributors:
+ *
+ * Hirotaka Matsumoto - Initial implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.trs;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.j2bugzilla.rpc.BugSearch;
+
+/**
+ * In addition to com.j2bugzilla.rpc.BugSearch, this class accepts "last_change_tim"
+ *
+ */
+public class BugSearch2 extends BugSearch {
+ private Date dayAfter;
+
+ public BugSearch2(SearchQuery... queries) {
+ super(queries);
+ }
+
+ @Override
+ public Map<Object, Object> getParameterMap() {
+ Map<Object, Object> ret = new HashMap<Object, Object>(super.getParameterMap());
+ if (dayAfter != null) {
+ ret.put("last_change_time", dayAfter);//$NON-NLS-1$
+ }
+ return ret;
+ }
+
+ public void setDayAfter(Date dayAfter) {
+ this.dayAfter = dayAfter;
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/ChangeBugzillaHistories.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/ChangeBugzillaHistories.java
new file mode 100644
index 0000000..335736e
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/ChangeBugzillaHistories.java
@@ -0,0 +1,418 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * * Contributors:
+ *
+ * Hirotaka Matsumoto - Initial implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.trs;
+
+import java.io.IOException;
+import java.net.URI;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TimeZone;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.lyo.core.trs.Base;
+import org.eclipse.lyo.core.trs.ChangeEvent;
+import org.eclipse.lyo.core.trs.ChangeLog;
+import org.eclipse.lyo.core.trs.Creation;
+import org.eclipse.lyo.core.trs.Modification;
+import org.eclipse.lyo.core.trs.TRSConstants;
+import org.eclipse.lyo.oslc4j.bugzilla.BugzillaManager;
+import org.eclipse.lyo.oslc4j.bugzilla.jbugzx.rpc.GetAccessibleProducts;
+
+import com.j2bugzilla.base.Bug;
+import com.j2bugzilla.base.BugzillaConnector;
+import com.j2bugzilla.base.Product;
+import com.j2bugzilla.rpc.BugSearch;
+import com.j2bugzilla.rpc.GetProduct;
+
+/**
+ * This class represents the list of History data in Bugzilla
+ */
+public class ChangeBugzillaHistories {
+ private static final int MAXNUMBEROGBUGS = 100;
+ private static final SimpleDateFormat XSD_DATETIME_FORMAT;
+ static {
+ XSD_DATETIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");//$NON-NLS-1$
+ XSD_DATETIME_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));//$NON-NLS-1$
+ }
+
+ private ChangeBugzillaHistories() {
+ }
+
+ private static HistoryData[] getHistory(HttpServletRequest httpServletRequest, Date dayAfter) {
+ // See
+ // org.eclipse.lyo.oslc4j.bugzilla.servlet.ServiceProviderCatalogSingleton.initServiceProvidersFromProducts(HttpServletRequest)
+ try {
+ BugzillaConnector bc = BugzillaManager.getBugzillaConnector(httpServletRequest);
+ List<String> productIds = new ArrayList<String>();
+ if (bc != null) {
+ // get product ids
+ GetAccessibleProducts getProductIds = new GetAccessibleProducts();
+ bc.executeMethod(getProductIds);
+ Integer[] ids = getProductIds.getIds();
+ for (Integer p : ids) {
+ productIds.add(Integer.toString(p));
+ }
+
+ // get basePath
+ // String basePath = BugzillaManager.getBugzServiceBase(); // this is
+ // http://<hostname>:<port>/OSLC4JBugzilla/services
+
+ // get bugs from each product
+ List<HistoryData> allhistories = new ArrayList<HistoryData>();
+ for (String productid : productIds) {
+ List<Bug> bugList = ChangeBugzillaHistories.getBugsByProduct(httpServletRequest, productid, /* page */0, /* limit */ChangeBugzillaHistories.MAXNUMBEROGBUGS, dayAfter);
+ for (Bug bug : bugList) {
+ Collections.addAll(allhistories, BugzillaManager.getBugHistoryById(httpServletRequest, bug, productid, Integer.toString(bug.getID()), dayAfter));
+ }
+ }
+ Collections.sort(allhistories, new Comparator<HistoryData>() {
+ public int compare(HistoryData object1, HistoryData object2) {
+ return object1.getTimestamp().compareTo(object2.getTimestamp()) * -1; // reverse sort, so new -> old
+ }
+ });
+ HistoryData[] result = new HistoryData[allhistories.size()];
+ allhistories.toArray(result);
+ return result;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new WebApplicationException(e, Status.INTERNAL_SERVER_ERROR);
+ }
+ return null;
+ }
+
+ /*
+ * Retrieve the old implementation
+ */
+ /**
+ * Create a list of Bugs for a product ID using paging
+ *
+ * @param httpServletRequest
+ * @param productIdString
+ * @param page
+ * @param limit
+ * @return The list of bugs, paged if necessary
+ * @throws IOException
+ * @throws ServletException
+ */
+ private static List<Bug> getBugsByProduct(final HttpServletRequest httpServletRequest,
+ final String productIdString, int page, int limit, Date dayAfter) throws IOException, ServletException {
+ List<Bug> results = null;
+ try {
+ final BugzillaConnector bc = BugzillaManager.getBugzillaConnector(httpServletRequest);
+ final String pageString = httpServletRequest.getParameter("page");//$NON-NLS-1$
+
+ if (null != pageString) {
+ page = Integer.parseInt(pageString);
+ }
+ int productId = Integer.parseInt(productIdString);
+ final GetProduct getProducts = new GetProduct(productId);
+ if (bc != null) {
+ bc.executeMethod(getProducts);
+ final Product product = getProducts.getProduct();
+ final BugSearch bugSearch = ChangeBugzillaHistories.createBugSearch(page, limit, product, dayAfter);
+ bc.executeMethod(bugSearch);
+ results = bugSearch.getSearchResults();
+ } else {
+ System.err.println("Bugzilla Connector not initialized - check bugz.properties");//$NON-NLS-1$
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new WebApplicationException(e);
+ }
+ return results;
+ }
+
+ private static BugSearch createBugSearch(int page, int limit, Product product, Date dayAfter) {
+ BugSearch.SearchQuery productQuery = new BugSearch.SearchQuery(
+ BugSearch.SearchLimiter.PRODUCT, product.getName());
+ BugSearch.SearchQuery limitQuery = new BugSearch.SearchQuery(
+ BugSearch.SearchLimiter.LIMIT, (limit + 1) + "");//$NON-NLS-1$
+ BugSearch.SearchQuery offsetQuery = new BugSearch.SearchQuery(
+ BugSearch.SearchLimiter.OFFSET, (page * limit) + "");//$NON-NLS-1$
+ if (dayAfter == null) {
+ return new BugSearch(productQuery, limitQuery, offsetQuery);
+ }
+ BugSearch2 search = new BugSearch2(productQuery, limitQuery, offsetQuery);
+ search.setDayAfter(new Date(dayAfter.getTime()+1000)); // +1s : bugs dates > dayAfter
+ return search;
+ }
+
+ /**
+ * Mutex
+ */
+ private static String mutex = "";//$NON-NLS-1$
+ /**
+ * List of Base Resources (pageNum, List<Base>)
+ */
+ private static Map<String, Base> baseResouces;
+ private static Date mostRecentChangeLogDate;
+ private static Date lastBaseResourceUpdatedDate;
+ private static long UPDATEINTERVAL;
+ static {
+ Properties props = new Properties();
+ try {
+ props.load(BugzillaManager.class.getResourceAsStream("/bugz.properties"));//$NON-NLS-1$
+ String interval = props.getProperty("rebuild_interval");//$NON-NLS-1$
+ if ((interval != null) && (interval.length() != 0)) {
+ UPDATEINTERVAL = Integer.valueOf(interval).longValue();
+ }
+ if (UPDATEINTERVAL == 0) {
+ UPDATEINTERVAL = 5 * 60 * 1000; // 5 min = 300s = 300000 milliseconds
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ /**
+ * List of Change Logs
+ */
+ private static Map<String, ChangeLog> changeLogs;
+ /**
+ * Saved Bugzilla History
+ */
+ private static HistoryData[] prevBugHistories;
+ /**
+ * Page Limit for Base Resources
+ */
+ private static final int BASE_PAGELIMIT = 3;
+ /**
+ * Page Limit for ChangeLogs
+ */
+ private static final int CHANGELOGS_PAGELIMIT = 3;
+
+ /**
+ * Build Bugzilla ChangeLogs diff after mostRecentChangeData
+ */
+ private static HistoryData[] buildChangeLogsDiff(HttpServletRequest httpServletRequest) {
+ return ChangeBugzillaHistories.getHistory(httpServletRequest, mostRecentChangeLogDate);
+ }
+
+ /**
+ * Build Bugzilla Base resources and ChangeLogs
+ */
+ private static void buildBaseResourcesAndChangeLogsInternal(HttpServletRequest httpServletRequest) {
+ Date nowDate = new Date();
+ if ((lastBaseResourceUpdatedDate != null) &&
+ (nowDate.getTime() - lastBaseResourceUpdatedDate.getTime() > UPDATEINTERVAL)) {
+ mostRecentChangeLogDate = null; // enforce to build all
+ }
+ boolean buildAll = ((mostRecentChangeLogDate == null) || (baseResouces == null));
+
+ HistoryData[] updatedHistories = null;
+ if (!buildAll) {
+ // Get only updated Histories
+ updatedHistories = ChangeBugzillaHistories.buildChangeLogsDiff(httpServletRequest);
+ if ((updatedHistories == null) || (updatedHistories.length == 0)) {
+ return;
+ }
+ } else {
+ baseResouces = null;
+ mostRecentChangeLogDate = null;
+ lastBaseResourceUpdatedDate = nowDate;
+ }
+
+ changeLogs = null;
+
+ int basePagenum = 1;
+ int changeLogPageNum = 1;
+
+ URI nilURI = URI.create(TRSConstants.RDF_NIL);
+
+ // even if no change logs, Base is necessary
+ Base base = null;
+ Base prevBase = null;
+ if (buildAll) {
+ base = new Base();
+ base.setAbout(URI.create(BugzillaManager.getBugzServiceBase()
+ + "/trs/" + TRSConstants.TRS_TERM_BASE));//$NON-NLS-1$
+ base.setNextPage(nilURI);
+ baseResouces = new HashMap<String, Base>();
+ baseResouces.put(String.valueOf(basePagenum), base);
+ }
+
+ // Try to get Bugzilla histories now.
+ HistoryData[] histories = null;
+ if (buildAll) {
+ histories = ChangeBugzillaHistories.getHistory(httpServletRequest, null);
+ if (histories.length == 0) {
+ return;
+ }
+ } else {
+ int newSize = prevBugHistories != null ? prevBugHistories.length : 0;
+ newSize += updatedHistories != null ? updatedHistories.length : 0;
+ if (newSize == 0) {
+ return;
+ }
+ histories = new HistoryData[newSize];
+ int start = 0;
+ if ((updatedHistories != null) && (updatedHistories.length > 0)) {
+ System.arraycopy(updatedHistories, 0, histories, start, updatedHistories.length);
+ start = updatedHistories.length;
+ }
+ if ((prevBugHistories != null) && (prevBugHistories.length > 0)) {
+ System.arraycopy(prevBugHistories, 0, histories, start, prevBugHistories.length);
+ start = prevBugHistories.length;
+ }
+ }
+ prevBugHistories = new HistoryData[histories.length];
+ System.arraycopy(histories, 0, prevBugHistories, 0, histories.length);
+
+ ChangeLog changeLog = null;
+ ChangeLog prevChangeLog = null;
+
+ int changeOrder = histories.length;
+ int currentNumberOfMember = 0;
+ int currentNumberOfChangeLog = 0;
+ URI mostRecentChangeEventURI = null;
+ List<URI> allmembers = buildAll ? new ArrayList<URI>(histories.length) : null;
+ for (HistoryData historyData : histories) {
+ URI uri = historyData.getUri();
+ String changedUriTemplate = "urn:urn-3:" + //$NON-NLS-1$
+ "cm1.example.com" + //$NON-NLS-1$
+ ":" + //$NON-NLS-1$
+ XSD_DATETIME_FORMAT.format(historyData.getTimestamp()) + ":" + //$NON-NLS-1$
+ changeOrder;
+ URI changedUri = URI.create(changedUriTemplate);
+ ChangeEvent ce = historyData.getType() == HistoryData.CREATED ?
+ new Creation(changedUri, uri, changeOrder) : new Modification(changedUri, uri, changeOrder);
+ if (mostRecentChangeEventURI == null) {
+ mostRecentChangeEventURI = changedUri;
+ mostRecentChangeLogDate = historyData.getTimestamp();
+ }
+
+ // ChangeLog Page
+ if (changeLog == null) {
+ URI prevPage;
+ if (changeLogs == null) {
+ prevPage = URI.create(BugzillaManager.getBugzServiceBase()
+ + "/trs/" + TRSConstants.TRS_TERM_CHANGE_LOG);//$NON-NLS-1$
+ } else {
+ prevPage = URI
+ .create(BugzillaManager.getBugzServiceBase()
+ + "/trs/" + TRSConstants.TRS_TERM_CHANGE_LOG + "/" + String.valueOf(changeLogPageNum + 1));//$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (prevChangeLog != null) {
+ prevChangeLog.setPrevious(prevPage);
+ prevChangeLog = null;
+ }
+ if (changeLogs != null) {
+ changeLogPageNum++;
+ }
+ changeLog = new ChangeLog();
+ changeLog.setAbout(prevPage);
+ changeLog.setPrevious(nilURI);
+ if (changeLogs == null) {
+ changeLogs = new HashMap<String, ChangeLog>();
+ }
+ changeLogs.put(String.valueOf(changeLogPageNum), changeLog);
+ }
+
+ changeLog.getChanges().add(ce);
+ currentNumberOfChangeLog++;
+
+ if (buildAll && !allmembers.contains(uri)) {
+ // Base Page
+ if (base == null) {
+ URI nextPage = URI.create(BugzillaManager.getBugzServiceBase()
+ + "/trs/" + TRSConstants.TRS_TERM_BASE + "/" + String.valueOf(basePagenum + 1));//$NON-NLS-1$ //$NON-NLS-2$
+ if (prevBase != null) {
+ prevBase.setNextPage(nextPage);
+ prevBase = null;
+ }
+ basePagenum++;
+ base = new Base();
+ base.setAbout(URI.create(BugzillaManager.getBugzServiceBase()
+ + "/trs/" + TRSConstants.TRS_TERM_BASE));//$NON-NLS-1$
+ base.setNextPage(nilURI);
+ baseResouces.put(String.valueOf(basePagenum), base);
+ }
+ base.getMembers().add(uri);// rdfs:member is mandatory
+ currentNumberOfMember++;
+ allmembers.add(uri);
+ }
+ changeOrder--;
+
+ // Base Page
+ if ((buildAll) && (currentNumberOfMember >= BASE_PAGELIMIT)) {
+ prevBase = base;
+ base = null;
+ currentNumberOfMember = 0;
+ }
+ // ChangeLog Page
+ if (currentNumberOfChangeLog >= CHANGELOGS_PAGELIMIT) {
+ prevChangeLog = changeLog;
+ changeLog = null;
+ currentNumberOfChangeLog = 0;
+ }
+ }
+ // Base resource's CutoffEvent is most recent Change event.
+ // Since the order of the returned HistoryData is "new -> old",
+ // the first one is the most recent.
+ if (buildAll) {
+ ((Base) baseResouces.get("1")).setCutoffEvent(mostRecentChangeEventURI);//$NON-NLS-1$
+ }
+ }
+
+ public static void buildBaseResourcesAndChangeLogs(
+ HttpServletRequest httpServletRequest) {
+ synchronized (mutex) {
+ ChangeBugzillaHistories.buildBaseResourcesAndChangeLogsInternal(httpServletRequest);
+ }
+ }
+
+ /**
+ * Return pagenum's Base resource
+ *
+ * @param pagenum
+ * @param httpServletRequest
+ * @return
+ */
+ public static Base getBaseResource(String pagenum,
+ HttpServletRequest httpServletRequest) {
+ synchronized (mutex) {
+ ChangeBugzillaHistories.buildBaseResourcesAndChangeLogsInternal(httpServletRequest);
+ return baseResouces != null ? baseResouces.get(pagenum) : null;
+ }
+ }
+
+ /**
+ * Return pagenum's ChangeLog
+ *
+ * @param pagenum
+ * @param httpServletRequest
+ * @return
+ */
+ public static ChangeLog getChangeLog(String pagenum,
+ HttpServletRequest httpServletRequest) {
+ synchronized (mutex) {
+ ChangeBugzillaHistories.buildBaseResourcesAndChangeLogsInternal(httpServletRequest);
+ // changeLogs might be null
+ return changeLogs != null ? changeLogs.get(pagenum) : null;
+ }
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/GetComments.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/GetComments.java
new file mode 100644
index 0000000..d4fabc4
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/GetComments.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * * Contributors:
+ *
+ * Hirotaka Matsumoto - Initial implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.trs;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.j2bugzilla.base.BugzillaMethod;
+
+/**
+ *
+ */
+public class GetComments implements BugzillaMethod {
+ /**
+ * The method name for this {@link BugzillaMethod}
+ */
+ private static final String GET_COMMENTS = "Bug.comments"; //$NON-NLS-1$
+
+ private Map<Object, Object> hash = new HashMap<Object, Object>();
+ private Map<Object, Object> params = new HashMap<Object, Object>();
+ private int bugid;
+
+ public GetComments() {
+ }
+
+ public GetComments(int id) {
+ bugid = id;
+ params.put("ids", id);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.j2bugzilla.base.BugzillaMethod#setResultMap(java.util.Map)
+ */
+ public void setResultMap(Map<Object, Object> hash) {
+ this.hash = hash;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.j2bugzilla.base.BugzillaMethod#getParameterMap()
+ */
+ public Map<Object, Object> getParameterMap() {
+ return Collections.unmodifiableMap(params);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.j2bugzilla.base.BugzillaMethod#getMethodName()
+ */
+ public String getMethodName() {
+ return GET_COMMENTS;
+ }
+
+ /**
+ * Get the list of comments
+ *
+ * These comments are mapped to "changed" events.
+ */
+ public Date[] getModifiedTimestamps() {
+ List<Date> result = new ArrayList<Date>();
+
+ if (hash.containsKey("bugs")) { //$NON-NLS-1$
+ @SuppressWarnings("unchecked")
+ Map<String, Object> bugMap = (HashMap<String, Object>) hash.get("bugs");//$NON-NLS-1$
+ if (bugMap.containsKey(Integer.toString(bugid))) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> commentsMap = (HashMap<String, Object>) bugMap
+ .get(Integer.toString(bugid));
+ if (commentsMap.containsKey("comments")) {//$NON-NLS-1$
+ Object[] comments = (Object[]) commentsMap.get("comments"); //$NON-NLS-1$
+ if (comments.length == 0) {
+ return (Date[]) result.toArray(); // early return if map is empty;
+ }
+ for (Object o : comments) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> comment = (HashMap<String, Object>) o;
+ if (comment.containsKey("time")) {//$NON-NLS-1$
+ result.add((Date) comment.get("time")); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ }
+ Date[] copyresult = new Date[result.size()];
+ return result.toArray(copyresult);
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/GetHistory.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/GetHistory.java
new file mode 100644
index 0000000..e7dabcb
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/GetHistory.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * * Contributors:
+ *
+ * Hirotaka Matsumoto - Initial implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.trs;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.j2bugzilla.base.BugzillaMethod;
+
+/**
+ *
+ */
+public class GetHistory implements BugzillaMethod {
+ /**
+ * The method name for this {@link BugzillaMethod}
+ */
+ private static final String GET_HISTORY = "Bug.history"; //$NON-NLS-1$
+
+ private Map<Object, Object> hash = new HashMap<Object, Object>();
+ private Map<Object, Object> params = new HashMap<Object, Object>();
+
+ public GetHistory() {
+ }
+
+ public GetHistory(int id) {
+ params.put("ids", id);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.j2bugzilla.base.BugzillaMethod#setResultMap(java.util.Map)
+ */
+ public void setResultMap(Map<Object, Object> hash) {
+ this.hash = hash;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.j2bugzilla.base.BugzillaMethod#getParameterMap()
+ */
+ public Map<Object, Object> getParameterMap() {
+ return Collections.unmodifiableMap(params);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.j2bugzilla.base.BugzillaMethod#getMethodName()
+ */
+ public String getMethodName() {
+ return GET_HISTORY;
+ }
+
+ /**
+ * Get the list of history
+ *
+ * This history has only "changed" events.
+ */
+ public Date[] getModifiedTimestamps() {
+ List<Date> result = new ArrayList<Date>();
+
+ if (hash.containsKey("bugs")) { //$NON-NLS-1$
+ Object[] bugs = (Object[]) hash.get("bugs"); //$NON-NLS-1$
+ if (bugs.length == 0) {
+ return (Date[]) result.toArray(); // early return if map is empty
+ }
+ for (Object o : bugs) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> bugMap = (HashMap<String, Object>) o;
+ if (bugMap.containsKey("history")) { //$NON-NLS-1$
+ Object[] histories = (Object[]) bugMap.get("history"); //$NON-NLS-1$
+ for (Object h : histories) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> historyMap = (Map<String, Object>) h;
+ if (historyMap.containsKey("when")) { //$NON-NLS-1$
+ result.add((Date) historyMap.get("when")); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ }
+ Date[] copyresult = new Date[result.size()];
+ return result.toArray(copyresult);
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/GetProduct.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/GetProduct.java
new file mode 100644
index 0000000..28dca6a
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/GetProduct.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * * Contributors:
+ *
+ * Hirotaka Matsumoto - Initial implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.trs;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.j2bugzilla.base.BugzillaMethod;
+
+/**
+ *
+ */
+public class GetProduct implements BugzillaMethod {
+ /**
+ * The method name for this {@link BugzillaMethod}
+ */
+ private static final String GET_PRPDUCT = "Product.get"; //$NON-NLS-1$
+
+ private Map<Object, Object> hash = new HashMap<Object, Object>();
+ private Map<Object, Object> params = new HashMap<Object, Object>();
+// private String productName;
+// private Integer[] ids;
+ private int[] ids;
+
+// public GetProduct(String productName) {
+// this.productName = productName;
+// params.put("names", productName);
+// }
+
+ public GetProduct(Integer[] ids) {
+ this.ids = new int[ids.length];
+ int offset = 0;
+ for(Integer id : ids ) {
+ ids[offset] = id.intValue();
+ offset++;
+ }
+ params.put("ids", ids);
+ }
+
+ /* (non-Javadoc)
+ * @see com.j2bugzilla.base.BugzillaMethod#setResultMap(java.util.Map)
+ */
+ @Override
+ public void setResultMap(Map<Object, Object> hash) {
+ this.hash = hash;
+ }
+
+ /* (non-Javadoc)
+ * @see com.j2bugzilla.base.BugzillaMethod#getParameterMap()
+ */
+ @Override
+ public Map<Object, Object> getParameterMap() {
+ return Collections.unmodifiableMap(params);
+ }
+
+ /* (non-Javadoc)
+ * @see com.j2bugzilla.base.BugzillaMethod#getMethodName()
+ */
+ @Override
+ public String getMethodName() {
+ return GET_PRPDUCT;
+ }
+
+ /**
+ * Return the corresponding Product ID
+ */
+ public String getProductID(String productName) {
+ if (hash.containsKey("products")) {//$NON-NLS-1$
+ Object[] products = (Object[]) hash.get("products");//$NON-NLS-1$
+ if (products != null) {
+ for(Object product : products) {
+ Map<String, Object> productMap = (HashMap<String, Object>)product;
+ if (productMap.containsKey("name")) {//$NON-NLS-1$
+ String name = (String)productMap.get("name"); //$NON-NLS-1$
+ if ((name != null) && (name.equals(productName))) {
+ return ((Integer)productMap.get("id")).toString(); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ }
+ return "";//$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/HistoryData.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/HistoryData.java
new file mode 100644
index 0000000..4ed1154
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/trs/HistoryData.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * * Contributors:
+ *
+ * Hirotaka Matsumoto - Initial implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.trs;
+
+import java.net.URI;
+import java.util.Date;
+
+/**
+ * This class represents the one hisotry data in Bugzilla bug
+ */
+public class HistoryData {
+ final public static String CREATED="Created"; // trs:Creation //$NON-NLS-1$
+ final public static String MODIFIED="Modified"; // trs:Modification //$NON-NLS-1$
+
+ private int productid; // Bugzilla product id
+ private int id; // Bugzilla id
+ private Date timestamp; // Time stamp;
+ private URI uri; // OSLC link
+ private String type = CREATED; // trs:Creation or trs:Modification
+
+ private HistoryData() {
+ }
+
+ public static HistoryData getInstance(int productid, int id, Date timestamp, URI uri, String type) {
+ HistoryData h = new HistoryData();
+ h.productid = productid;
+ h.id = id;
+ h.timestamp = timestamp;
+ h.uri = uri;
+ h.type = type;
+ return h;
+ }
+
+ /**
+ * @return the productid
+ */
+ public int getProductid() {
+ return productid;
+ }
+
+ /**
+ * @return the id
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * @return the timestamp
+ */
+ public Date getTimestamp() {
+ return timestamp;
+ }
+
+ /**
+ * @return the url
+ */
+ public URI getUri() {
+ return uri;
+ }
+
+ /**
+ * @return the type
+ */
+ public String getType() {
+ return type;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return "id="+Integer.toString(getId())+ ", "+//$NON-NLS-1$ //$NON-NLS-2$
+ "ProductId="+Integer.toString(getProductid())+ ", "+//$NON-NLS-1$ //$NON-NLS-2$
+ "Type=" + getType()+ ", "+//$NON-NLS-1$ //$NON-NLS-2$
+ "Timestamp=" + getTimestamp()+ ", "+//$NON-NLS-1$ //$NON-NLS-2$
+ "URI="+getUri()+"\n";//$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/BugzillaHttpClient.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/BugzillaHttpClient.java
new file mode 100644
index 0000000..9b0d368
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/BugzillaHttpClient.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Steve Pitschke - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.StatusLine;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.params.ClientPNames;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.PlainSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.scheme.SchemeSocketFactory;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.conn.PoolingClientConnectionManager;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.CoreConnectionPNames;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.HttpContext;
+import org.eclipse.lyo.oslc4j.bugzilla.Credentials;
+
+/**
+ * Utility for doing HTTP GET's against Bugzilla server.
+ */
+public class BugzillaHttpClient
+{
+ public
+ BugzillaHttpClient(
+ String rootURL,
+ Credentials credentials
+ ) throws UnsupportedEncodingException
+ {
+ this.rootURL = rootURL;
+
+ authorization = "&Bugzilla_login=" +
+ URLEncoder.encode(credentials.getUsername(), "UTF-8") +
+ "&Bugzilla_password=" +
+ URLEncoder.encode(credentials.getPassword(), "UTF-8");
+
+ httpClient = getHttpClient();
+
+ cntxt = new BasicHttpContext();
+ }
+
+ public InputStream
+ httpGet(String path) throws IOException
+ {
+ HttpGet get = new HttpGet(rootURL + "/" + path + authorization);
+
+ HttpResponse response = httpClient.execute(get, cntxt);
+ StatusLine status = response.getStatusLine();
+
+ if (status.getStatusCode() != HttpStatus.SC_OK) {
+ throw new IOException(status.getReasonPhrase());
+ }
+
+ return response.getEntity().getContent();
+ }
+
+ private static HttpClient
+ getHttpClient()
+ {
+ SSLContext sc = getTrustingSSLContext();
+ SchemeSocketFactory sf = new SSLSocketFactory(sc);
+
+ Scheme scheme = new Scheme("https", 443, sf);
+ SchemeRegistry schemeRegistry = new SchemeRegistry();
+
+ schemeRegistry.register(scheme);
+
+ sf = PlainSocketFactory.getSocketFactory();
+ scheme = new Scheme("http", 80, sf);
+
+ schemeRegistry.register(scheme);
+
+ ClientConnectionManager clientConnectionManager =
+ new PoolingClientConnectionManager(schemeRegistry);
+ HttpParams clientParams = new BasicHttpParams();
+
+ clientParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, TIMEOUT);
+ clientParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, TIMEOUT);
+ clientParams.setParameter(ClientPNames.HANDLE_REDIRECTS, true);
+
+ return new DefaultHttpClient(clientConnectionManager, clientParams);
+ }
+
+ private static SSLContext
+ getTrustingSSLContext()
+ {
+ // Create a trust manager that does not validate certificate chains
+ TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+ public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
+ }
+
+ public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
+ }
+ } };
+
+ try {
+ SSLContext sc = SSLContext.getInstance("SSL");
+ sc.init(null, trustAllCerts, new java.security.SecureRandom());
+ return sc;
+ } catch (KeyManagementException e) {
+ e.printStackTrace();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ private final String rootURL;
+ private final String authorization;
+ private final HttpClient httpClient;
+ private final HttpContext cntxt;
+
+ private static final int TIMEOUT = 30000; // 30 seconds
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/HttpUtils.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/HttpUtils.java
new file mode 100644
index 0000000..784aaaa
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/HttpUtils.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.utils;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import net.oauth.server.OAuthServlet;
+
+import org.apache.ws.commons.util.Base64;
+import org.apache.ws.commons.util.Base64.DecodingException;
+import org.eclipse.lyo.oslc4j.bugzilla.BugzillaManager;
+import org.eclipse.lyo.oslc4j.bugzilla.Credentials;
+import org.eclipse.lyo.oslc4j.bugzilla.exception.BugzillaOAuthException;
+import org.eclipse.lyo.oslc4j.bugzilla.exception.RestException;
+import org.eclipse.lyo.oslc4j.bugzilla.exception.UnauthorizedException;
+//import org.eclipse.lyo.oslc4j.bugzilla.resources.Error;
+import org.eclipse.lyo.server.oauth.core.OAuthConfiguration;
+
+/**
+ * Utilities for working with HTTP requests and responses.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public class HttpUtils {
+
+ public static final String AUTHORIZATION_HEADER = "Authorization";
+ public static final String WWW_AUTHENTICATE_HEADER = "WWW-Authenticate";
+ private static final String BASIC_AUTHORIZATION_PREFIX = "Basic ";
+ private static final String BASIC_AUTHENTICATION_CHALLENGE = BASIC_AUTHORIZATION_PREFIX
+ + "realm=\"" + BugzillaManager.REALM + "\"";
+ private static final String OAUTH_AUTHORIZATION_PREFIX = "OAuth ";
+ private static final String OAUTH_AUTHENTICATION_CHALLENGE = OAUTH_AUTHORIZATION_PREFIX
+ + "realm=\"" + BugzillaManager.REALM + "\"";
+
+ /**
+ * Gets the credentials from an HTTP request.
+ *
+ * @param request
+ * the request
+ * @return the Bugzilla credentials or <code>null</code> if the request did
+ * not contain an <code>Authorization</code> header
+ * @throws UnauthorizedException
+ * on problems reading the credentials from the
+ * <code>Authorization</code> request header
+ */
+ public static Credentials getCredentials(HttpServletRequest request)
+ throws UnauthorizedException {
+ String authorizationHeader = request.getHeader(AUTHORIZATION_HEADER);
+ if (authorizationHeader == null || "".equals(authorizationHeader)) {
+ return null;
+ }
+
+ Credentials credentials = new Credentials();
+ if (!authorizationHeader.startsWith(HttpUtils.BASIC_AUTHORIZATION_PREFIX)) {
+ throw new UnauthorizedException(
+ "Only basic access authentication is supported.");
+ }
+
+ String encodedString = authorizationHeader.substring(HttpUtils.BASIC_AUTHORIZATION_PREFIX.length());
+ try {
+ String unencodedString = new String(Base64.decode(encodedString), "UTF-8");
+ int seperator = unencodedString.indexOf(':');
+ if (seperator == -1) {
+ throw new UnauthorizedException("Invalid Authorization header value.");
+ }
+
+ credentials.setUsername(unencodedString.substring(0, seperator));
+ credentials.setPassword(unencodedString.substring(seperator + 1));
+ } catch (DecodingException e) {
+ throw new UnauthorizedException("Username and password not Base64 encoded.");
+ } catch (UnsupportedEncodingException e) {
+ throw new UnauthorizedException("Invalid Authorization header value.");
+ }
+
+ return credentials;
+ }
+
+ public static void sendUnauthorizedResponse(HttpServletResponse response,
+ UnauthorizedException e) throws IOException, ServletException {
+ if (e instanceof BugzillaOAuthException) {
+ OAuthServlet.handleException(response, e, BugzillaManager.REALM);
+ } else {
+ // Accept basic access or OAuth authentication.
+ response.addHeader(WWW_AUTHENTICATE_HEADER,
+ OAUTH_AUTHENTICATION_CHALLENGE);
+ response.addHeader(WWW_AUTHENTICATE_HEADER,
+ BASIC_AUTHENTICATION_CHALLENGE);
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ }
+
+
+
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/StringUtils.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/StringUtils.java
new file mode 100644
index 0000000..3e29cb4
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/StringUtils.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.utils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.StringTokenizer;
+
+public class StringUtils {
+
+ private static final String LS = System.getProperty("line.separator");
+
+ public static String streamToString(InputStream is) throws IOException {
+ StringBuffer sb = new StringBuffer();
+ BufferedReader in = new BufferedReader(new InputStreamReader(is));
+ String line;
+ while ((line = in.readLine()) != null) {
+ sb.append(line);
+ sb.append(LS);
+ }
+ return sb.toString();
+ }
+
+ public static String forHtml(String expr) {
+ // convert each line to a paragraph
+ StringTokenizer st = new StringTokenizer(expr, "\n"); //$NON-NLS-1$
+ StringBuffer sb = new StringBuffer();
+ while( st.hasMoreTokens() ){
+ sb.append(XmlUtils.encode(st.nextToken()) + "<br/>"); //$NON-NLS-1$
+ }
+ return sb.toString();
+ }
+
+ public static String rfc2822(Date date ) {
+ String pattern = "EEE, dd MMM yyyy HH:mm:ss Z"; //$NON-NLS-1$
+ SimpleDateFormat format = new SimpleDateFormat(pattern);
+ return format.format(date);
+ }
+
+ public static Date rfc2822(String dateStr) throws ParseException {
+ String pattern = "EEE, dd MMM yyyy HH:mm:ss Z"; //$NON-NLS-1$
+ SimpleDateFormat format = new SimpleDateFormat(pattern);
+ return format.parse(dateStr);
+ }
+
+ @SuppressWarnings("nls")
+ public static String stringEscape(String title) {
+ return title.replaceAll("\\\\", "\\\\\\\\");
+ }
+
+ public static boolean isEmpty(String s) {
+ return s == null || s.length() == 0;
+ }
+
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/XmlUtils.java b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/XmlUtils.java
new file mode 100644
index 0000000..53ae461
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/java/org/eclipse/lyo/oslc4j/bugzilla/utils/XmlUtils.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.bugzilla.utils;
+
+import java.io.StringWriter;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.w3c.dom.Document;
+
+public class XmlUtils {
+
+ @SuppressWarnings("nls")
+ public static String encode(String exp) {
+ if( exp != null ) {
+ String encoded = exp.replaceAll("&", "&amp;");
+ encoded = encoded.replaceAll(">", "&gt;");
+ encoded = encoded.replaceAll("<", "&lt;");
+ encoded = encoded.replaceAll("\"", "&quot;");
+ encoded = encoded.replaceAll("'", "&apos;");
+ return encoded;
+ }
+ return "";
+ }
+
+ public static String prettyPrint( Document doc ) {
+ TransformerFactory tfactory = TransformerFactory.newInstance();
+ Transformer serializer;
+ StringWriter writer = new StringWriter();
+ try {
+ serializer = tfactory.newTransformer();
+ //Setup indenting to "pretty print"
+ serializer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+ serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ serializer.transform(new DOMSource(doc), new StreamResult(writer));
+ return writer.toString();
+ } catch (TransformerException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/resources/bugz.properties b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/resources/bugz.properties
new file mode 100644
index 0000000..c1faa32
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/resources/bugz.properties
@@ -0,0 +1,28 @@
+###############################################################################
+# Copyright (c) 2011,2012 IBM Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+#
+# The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+# and the Eclipse Distribution License is available at
+# http://www.eclipse.org/org/documents/edl-v10.php.
+#
+# Contributors:
+#
+# IBM Corporation - initial API and implementation
+###############################################################################
+bugzilla_uri=http://localhost/bugzilla/
+admin=root@localhost.here
+
+# Added in Lab 1.2
+admin_password=passw0rd
+adapter_host=localhost
+
+# This is used when all Base resources will be rebuilt.
+# If the request to get TRS is after "rebuild_interval"
+# milliseconds than the precious call, all Base Resources
+# will be rebuilt.
+rebuild_interval=300000
+
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/resources/jetty.xml b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/resources/jetty.xml
new file mode 100644
index 0000000..1cb6cb6
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/resources/jetty.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+ <!-- see also: http://download.eclipse.org/jetty/stable-7/apidocs/ -->
+
+ <!-- Configure a log
+
+ <New id="ServerLog" class="java.io.PrintStream">
+ <Arg>
+ <New class="org.eclipse.jetty.util.RolloverFileOutputStream">
+ <Arg><SystemProperty name="jetty.logs" default="." />/yyyy_mm_dd.stderrout.log</Arg>
+ <Arg type="boolean">false</Arg>
+ <Arg type="int">90</Arg>
+ <Arg><Call class="java.util.TimeZone" name="getTimeZone"><Arg>GMT</Arg></Call></Arg>
+ <Get id="ServerLogName" name="datedFilename"/>
+ </New>
+ </Arg>
+ </New>
+ <Call class="org.eclipse.jetty.util.log.Log" name="info"><Arg>Redirecting stderr/stdout to <Ref id="ServerLogName"/></Arg></Call>
+ <Call class="java.lang.System" name="setErr"><Arg><Ref id="ServerLog"/></Arg></Call>
+ <Call class="java.lang.System" name="setOut"><Arg><Ref id="ServerLog"/></Arg></Call>
+-->
+</Configure>
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/META-INF/MANIFEST.MF b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5e94951
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path:
+
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/WEB-INF/lib/.gitignore b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/WEB-INF/lib/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/WEB-INF/lib/.gitignore
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/WEB-INF/web.xml b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..af90358
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2012 IBM Corporation.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+
+ The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ and the Eclipse Distribution License is available at
+ http://www.eclipse.org/org/documents/edl-v10.php.
+
+ Contributors:
+
+ IBM Corporation - initial API and implementation
+ -->
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
+ <display-name>OSLC4JBugzillaAdapter</display-name>
+ <context-param>
+ <description>Scheme used for URI when registering ServiceProvider. Can be overridden by System property of the same name.</description>
+ <param-name>org.eclipse.lyo.oslc4j.bugzilla.scheme</param-name>
+ <param-value>http</param-value>
+ </context-param>
+ <context-param>
+ <description>Port used for URI when registering ServiceProvider. Can be overridden by System property of the same name.</description>
+ <param-name>org.eclipse.lyo.oslc4j.bugzilla.port</param-name>
+ <param-value>8085</param-value>
+ </context-param>
+ <listener>
+ <listener-class>org.eclipse.lyo.oslc4j.bugzilla.BugzillaManager</listener-class>
+ </listener>
+ <!--
+ <servlet>
+ <servlet-name>JAX-RS Servlet</servlet-name>
+ <servlet-class>org.apache.wink.server.internal.servlet.RestServlet</servlet-class>
+ <init-param>
+ <param-name>applicationConfigLocation</param-name>
+ <param-value>/WEB-INF/classes/org/eclipse/lyo/oslc4j/bugzilla/services/providers;/WEB-INF/classes/org/eclipse/lyo/oslc4j/bugzilla/services/resources;</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ -->
+ <servlet>
+ <servlet-name>JAX-RS Servlet</servlet-name>
+ <servlet-class>org.apache.wink.server.internal.servlet.RestServlet</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.eclipse.lyo.oslc4j.bugzilla.services.BugzillaApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JAX-RS Servlet</servlet-name>
+ <url-pattern>/services/*</url-pattern>
+ </servlet-mapping>
+ <servlet>
+ <servlet-name>restSdkAdmin</servlet-name>
+ <servlet-class>org.apache.wink.server.internal.servlet.AdminServlet</servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>restSdkAdmin</servlet-name>
+ <url-pattern>/admin</url-pattern>
+ </servlet-mapping>
+ <servlet>
+ <servlet-name>RootServicesService</servlet-name>
+ <servlet-class>org.eclipse.lyo.oslc4j.bugzilla.services.RootServicesService</servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>RootServicesService</servlet-name>
+ <url-pattern>/rootservices</url-pattern>
+ </servlet-mapping>
+ <filter>
+ <display-name>CredentialsFilter</display-name>
+ <filter-name>CredentialsFilter</filter-name>
+ <filter-class>org.eclipse.lyo.oslc4j.bugzilla.servlet.CredentialsFilter</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>CredentialsFilter</filter-name>
+ <url-pattern>/services/*</url-pattern>
+ </filter-mapping>
+</web-app> \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/bugzilla.js b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/bugzilla.js
new file mode 100644
index 0000000..8a8b9ac
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/bugzilla.js
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+function search(baseUrl){
+ var ie = window.navigator.userAgent.indexOf("MSIE");
+ list = document.getElementById("results");
+ list.options.length = 0;
+ var searchMessage = document.getElementById('searchMessage');
+ var loadingMessage = document.getElementById('loadingMessage');
+ xmlhttp = new XMLHttpRequest();
+ xmlhttp.onreadystatechange = function() {
+ if (xmlhttp.readyState==4 && xmlhttp.status==200) {
+ // populate results
+ txt = xmlhttp.responseText;
+ resp = eval('(' + txt + ')');
+ for( var i=0; i<resp.results.length; i=i+1 ) {
+ var item=document.createElement('option');
+ item.text = resp.results[i].title;
+ item.value = resp.results[i].resource;
+ if (ie > 0) {
+ list.add(item);
+ } else {
+ list.add(item, null);
+ }
+ }
+
+ searchMessage.style.display = 'block';
+ loadingMessage.style.display = 'none';
+ }
+ };
+ terms = document.getElementById("searchTerms").value;
+ xmlhttp.open("GET", baseUrl + "?terms=" + encodeURIComponent(terms), true);
+ searchMessage.style.display = 'none';
+ loadingMessage.style.display = 'block';
+ xmlhttp.send();
+}
+
+function create(baseUrl){
+ var form = document.getElementById("Create");
+ xmlhttp = new XMLHttpRequest();
+ xmlhttp.onreadystatechange = function() {
+ if (xmlhttp.readyState==4 && (xmlhttp.status==201)) {
+ txt = xmlhttp.responseText;
+ resp = eval('(' + txt + ')');
+ // Send response to listener
+ sendResponse(resp.title, resp.resource);
+ }
+ };
+ var postData="";
+ if (form.component) {
+ postData += "&component="+encodeURIComponent(form.component.value);
+ }
+ if (form.summary) {
+ postData += "&summary="+encodeURIComponent(form.summary.value);
+ }
+ if (form.version) {
+ postData += "&version="+encodeURIComponent(form.version.value);
+ }
+ if (form.op_sys) {
+ postData += "&op_sys="+encodeURIComponent(form.op_sys.value);
+ }
+ if (form.platform) {
+ postData += "&platform="+encodeURIComponent(form.platform.value);
+ }
+ if (form.description) {
+ postData += "&description="+encodeURIComponent(form.description.value);
+ }
+ xmlhttp.open("POST", baseUrl, true);
+ xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
+ xmlhttp.setRequestHeader("Content-length",postData.length);
+ xmlhttp.send(postData);
+}
+
+function select(){
+ list = document.getElementById("results");
+ if( list.length>0 && list.selectedIndex >= 0 ) {
+ option = list.options[list.selectedIndex];
+ sendResponse(option.text, option.value);
+ }
+}
+
+function sendResponse(label, url) {
+ var oslcResponse = 'oslc-response:{ "oslc:results": [ ' +
+ ' { "oslc:label" : "' + label + '", "rdf:resource" : "' + url + '"} ' +
+ ' ] }';
+
+ if (window.location.hash == '#oslc-core-windowName-1.0') {
+ // Window Name protocol in use
+ respondWithWindowName(oslcResponse);
+ } else if (window.location.hash == '#oslc-core-postMessage-1.0') {
+ // Post Message protocol in use
+ respondWithPostMessage(oslcResponse);
+ }
+}
+
+function sendCancelResponse() {
+ var oslcResponse = 'oslc-response:{ "oslc:results": [ ]}';
+
+ if (window.location.hash == '#oslc-core-windowName-1.0') {
+ // Window Name protocol in use
+ respondWithWindowName(oslcResponse);
+ } else if (window.location.hash == '#oslc-core-postMessage-1.0') {
+ // Post Message protocol in use
+ respondWithPostMessage(oslcResponse);
+ }
+}
+
+
+function respondWithWindowName(/*string*/ response) {
+ // Step #2: read the return URL
+ var returnURL = window.name;
+
+ // Step #4: send the response via the window.name variable
+ window.name = response;
+
+ // Step #5: indicate that user has responded
+ window.location.href = returnURL;
+
+}
+
+function respondWithPostMessage(/*string*/ response) {
+ if( window.parent != null ) {
+ window.parent.postMessage(response, "*");
+ } else {
+ window.postMessage(response, "*");
+ }
+}
+
+function cancel(){
+ sendCancelResponse();
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_collection_html.jsp b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_collection_html.jsp
new file mode 100644
index 0000000..5ebeeef
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_collection_html.jsp
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<%--
+ Copyright (c) 2011, 2012 IBM Corporation.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+
+ The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ and the Eclipse Distribution License is available at
+ http://www.eclipse.org/org/documents/edl-v10.php.
+
+ Contributors:
+
+ Sam Padgett - initial API and implementation
+ Michael Fiedler - adapted for OSLC4J
+--%>
+
+<%@page import="org.eclipse.lyo.oslc4j.bugzilla.resources.BugzillaChangeRequest"%>
+<%@page import="org.eclipse.lyo.oslc4j.core.model.ServiceProvider"%>
+<%@ page contentType="text/html" language="java" pageEncoding="UTF-8" %>
+<%@ page import="java.util.List" %>
+<%
+ List<BugzillaChangeRequest> changeRequests = (List<BugzillaChangeRequest>) request.getAttribute("results");
+ ServiceProvider serviceProvider = (ServiceProvider) request.getAttribute("serviceProvider");
+ String bugzillaUri = (String) request.getAttribute("bugzillaUri");
+ String queryUri = (String)request.getAttribute("queryUri");
+ String nextPageUri = (String)request.getAttribute("nextPageUri");
+
+%>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+ <title>Bugzilla OSLC Adapter: Service Provider for <%= serviceProvider.getTitle() + "(" + serviceProvider.getIdentifier() + ")" %></title>
+ <link href="<%= bugzillaUri %>/skins/standard/global.css" rel="stylesheet" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/standard/index.css" rel="stylesheet" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/standard/global.css" rel="alternate stylesheet" title="Classic" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/standard/index.css" rel="alternate stylesheet" title="Classic" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/contrib/Dusk/global.css" rel="stylesheet" title="Dusk" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/contrib/Dusk/index.css" rel="stylesheet" title="Dusk" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/custom/global.css" rel="stylesheet" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/custom/index.css" rel="stylesheet" type="text/css">
+ <link rel="shortcut icon" href="<%= bugzillaUri %>/images/favicon.ico">
+ </head>
+ <body onload="">
+
+ <div id="header">
+ <div id="banner"></div>
+ <table border="0" cellspacing="0" cellpadding="0" id="titles">
+ <tr>
+ <td id="title">
+ <p>
+ Bugzilla OSLC Adapter: Service Provider
+ </p>
+ </td>
+ <td id="information">
+ <p class="header_addl_info">
+ version 0.1
+ </p>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <div id="bugzilla-body">
+ <div id="page-index">
+
+ <img src="../../images/resources/bugzilla.gif" alt="icon" width="80" height="80" />
+
+ <h1>Query Results</h1>
+
+ <% for (BugzillaChangeRequest changeRequest : changeRequests) { %>
+ <p>Summary: <%= changeRequest.getTitle() %><br /><a href="<%= changeRequest.getAbout() %>">
+ <%= changeRequest.getAbout() %></a></p>
+ <% } %>
+ <% if (nextPageUri != null) { %><a href="<%= nextPageUri %>">Next Page</a><% } %>
+
+ </div>
+ </div>
+
+ <div id="footer">
+ <div class="intro"></div>
+ <div class="outro">
+ <div style="margin: 0 1em 1em 1em; line-height: 1.6em; text-align: left">
+ <b>OSLC Tools Adapter Server 0.1</b> brought to you by <a href="http://eclipse.org/lyo">Eclipse Lyo</a><br />
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
+
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_creator.jsp b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_creator.jsp
new file mode 100644
index 0000000..1ee29d9
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_creator.jsp
@@ -0,0 +1,141 @@
+<!DOCTYPE html>
+<%--
+ Copyright (c) 2011, 2012 IBM Corporation.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+
+ The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ and the Eclipse Distribution License is available at
+ http://www.eclipse.org/org/documents/edl-v10.php.
+
+ Contributors:
+
+ Sam Padgett - initial API and implementation
+ Michael Fiedler - adapted for OSLC4J
+--%>
+<%@ page contentType="text/html" language="java" pageEncoding="UTF-8" %>
+<%@ page import="java.util.List" %>
+<%@ page import="com.j2bugzilla.base.Product" %>
+<%
+ String bugzillaUri = (String) request.getAttribute("bugzillaUri");
+ Product product = (Product) request.getAttribute("product");
+ String creatorUri = (String) request.getAttribute("creatorUri");
+ List<String> operatingSystems = (List<String>) request
+ .getAttribute("operatingSystems");
+ List<String> components = (List<String>) request
+ .getAttribute("components");
+ List<String> platforms = (List<String>) request
+ .getAttribute("platforms");
+ List<String> versions = (List<String>) request
+ .getAttribute("versions");
+%>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+<title>Bugzilla OSLC Adapter: Resource Creator</title>
+<link href="<%=bugzillaUri%>/skins/standard/global.css" rel="stylesheet" type="text/css">
+<link href="<%=bugzillaUri%>/skins/standard/index.css" rel="stylesheet" type="text/css">
+<link href="<%=bugzillaUri%>/skins/standard/global.css" rel="alternate stylesheet" title="Classic" type="text/css">
+<link href="<%=bugzillaUri%>/skins/standard/index.css" rel="alternate stylesheet" title="Classic" type="text/css">
+<link href="<%=bugzillaUri%>/skins/contrib/Dusk/global.css" rel="stylesheet" title="Dusk" type="text/css">
+<link href="<%=bugzillaUri%>/skins/contrib/Dusk/index.css" rel="stylesheet" title="Dusk" type="text/css">
+<link href="<%=bugzillaUri%>/skins/custom/global.css" rel="stylesheet" type="text/css">
+<link href="<%=bugzillaUri%>/skins/custom/index.css" rel="stylesheet" type="text/css">
+<link rel="shortcut icon" href="<%=bugzillaUri%>/images/favicon.ico">
+<script type="text/javascript" src="../../../bugzilla.js"></script>
+</head>
+<body style="padding: 10px;">
+ <div id="bugzilla-body">
+ <form id="Create" method="POST" class="enter_bug_form">
+ <input name="product" type="hidden" value="<%=product.getName()%>" />
+
+ <table style="clear: both;">
+
+ <tr>
+ <th class="field_label required">Summary:</th>
+ <td><input name="summary" class="required text_input"
+ type="text" style="width: 400px" id="summary" required autofocus></td>
+ </tr>
+
+ <tr>
+ <th class="field_label">Component:</th>
+ <td><select name="component">
+ <%
+ for (String c : components) {
+ %>
+ <option value="<%=c%>"><%=c%></option>
+ <%
+ }
+ %>
+ </select></td>
+ </tr>
+
+ <tr>
+ <th class="field_label">Version:</th>
+ <td><select name="version">
+ <%
+ for (String v : versions) {
+ %>
+ <option value="<%=v%>"><%=v%></option>
+ <%
+ }
+ %>
+ </select></td>
+ </tr>
+
+ <tr>
+ <th class="field_label">OS:</th>
+ <td><select name="op_sys">
+ <%
+ for (String os : operatingSystems) {
+ %>
+ <option value="<%=os%>"><%=os%></option>
+ <%
+ }
+ %>
+ </select></td>
+ </tr>
+
+ <tr>
+ <th class="field_label">Platform:</th>
+ <td><select name="platform">
+ <%
+ for (String p : platforms) {
+ %>
+ <option value="<%=p%>"><%=p%></option>
+ <%
+ }
+ %>
+ </select></td>
+ </tr>
+
+ <tr>
+ <th class="field_label">Description:</th>
+ <td><textarea style="width: 400px; height: 150px;"
+ id="description" name="description"></textarea></td>
+ </tr>
+
+ <tr>
+ <td></td>
+ <td>
+ <input type="button"
+ value="Submit Bug"
+ onclick="javascript: create( '<%= creatorUri %>' )">
+ <input type="button" value="Cancel" onclick="javascript: cancel()">
+ </td>
+ </tr>
+ </table>
+
+ <div style="width: 500px;">
+
+ </div>
+
+ </form>
+
+ <div style="clear: both;"></div>
+ </div>
+</body>
+</html>
+
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_filtered_json.jsp b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_filtered_json.jsp
new file mode 100644
index 0000000..766e722
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_filtered_json.jsp
@@ -0,0 +1,33 @@
+<%--
+ Copyright (c) 2011, 2012 IBM Corporation.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+
+ The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ and the Eclipse Distribution License is available at
+ http://www.eclipse.org/org/documents/edl-v10.php.
+
+ Contributors:
+
+ Sam Padgett - initial API and implementation
+ Michael Fiedler - adapted for OSLC4J
+--%>
+<%@ page contentType="application/json" language="java" pageEncoding="UTF-8" %>
+<%@page import="org.eclipse.lyo.oslc4j.bugzilla.resources.BugzillaChangeRequest"%>
+<%@ page import="java.net.*,java.util.*" %>
+
+{
+<%
+List<BugzillaChangeRequest> results = (List<BugzillaChangeRequest>)request.getAttribute("results");
+%>
+results: [
+<% int i = 0; for (BugzillaChangeRequest b : results) { %>
+ <% if (i > 0) { %>,<% } %>
+ { "title" : "<%= b.getIdentifier() %>: <%= b.getTitle() %>",
+ "resource" : "<%= b.getAbout() %>"
+ }
+<% i++; } %>
+]
+}
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_preview_large.jsp b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_preview_large.jsp
new file mode 100644
index 0000000..9fe2dad
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_preview_large.jsp
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<%--
+ Copyright (c) 2011, 2012 IBM Corporation.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+
+ The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ and the Eclipse Distribution License is available at
+ http://www.eclipse.org/org/documents/edl-v10.php.
+
+ Contributors:
+
+ Sam Padgett - initial API and implementation
+ Michael Fiedler - adapt for OSLC4J
+--%>
+<%@ page contentType="text/html" language="java" pageEncoding="UTF-8" %>
+<%@ page import="java.net.*,java.util.*" %>
+<%@ page import="java.net.*,java.util.*,java.text.SimpleDateFormat" %>
+<%@ page import="org.eclipse.lyo.oslc4j.bugzilla.resources.BugzillaChangeRequest" %>
+<%@ page import="org.eclipse.lyo.oslc4j.bugzilla.resources.Person" %>
+<%
+BugzillaChangeRequest changeRequest = (BugzillaChangeRequest)request.getAttribute("changeRequest");
+String bugzillaUri = (String) request.getAttribute("bugzillaUri");
+String bugUri = (String)request.getAttribute("bugUri");
+
+String title = changeRequest.getTitle();
+Date createdDate = (Date) changeRequest.getCreated();
+SimpleDateFormat formatter = new SimpleDateFormat();
+String created = formatter.format(createdDate);
+Date modifiedDate = (Date) changeRequest.getModified();
+String modified = formatter.format(modifiedDate);
+String component = changeRequest.getComponent();
+String identifier = changeRequest.getIdentifier()+"";
+String opSys = changeRequest.getOperatingSystem();
+Person assigneePerson = (Person) changeRequest.getContributors().get(0);
+String assignee = "Unknown";
+if (assigneePerson != null)
+ assignee = assigneePerson.getMbox();
+%>
+<html>
+<head>
+<title>Change Request: <%=title %> (<%=identifier %>)</title>
+<link href="<%= bugzillaUri %>/skins/standard/global.css" rel="stylesheet" type="text/css">
+<link href="<%= bugzillaUri %>/skins/standard/index.css" rel="stylesheet" type="text/css">
+<link href="<%= bugzillaUri %>/skins/standard/global.css" rel="alternate stylesheet" title="Classic" type="text/css">
+<link href="<%= bugzillaUri %>/skins/standard/index.css" rel="alternate stylesheet" title="Classic" type="text/css">
+<link href="<%= bugzillaUri %>/skins/contrib/Dusk/global.css" rel="stylesheet" title="Dusk" type="text/css">
+<link href="<%= bugzillaUri %>/skins/contrib/Dusk/index.css" rel="stylesheet" title="Dusk" type="text/css">
+<link href="<%= bugzillaUri %>/skins/custom/global.css" rel="stylesheet" type="text/css">
+<link href="<%= bugzillaUri %>/skins/custom/index.css" rel="stylesheet" type="text/css">
+<link rel="shortcut icon" href="<%= bugzillaUri %>/images/favicon.ico">
+</head>
+<body>
+Large Compact Preview<hr/>
+URI: <a href="<%= bugUri %>"><%= bugUri %></a> <br/>
+Title: <%= title %><br/>
+Identifier: <%= identifier %><br/>
+Component: <%= component %> <br/>
+Operating System: <%= opSys %><br/>
+Created: <%= created %><br/>
+Assignee: <%= assignee %><br/>
+Last Modified: <%= modified %><br/>
+</body>
+</html> \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_preview_small.jsp b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_preview_small.jsp
new file mode 100644
index 0000000..41475ce
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_preview_small.jsp
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<!--
+ Copyright (c) 2011, 2012 IBM Corporation.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+
+ The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ and the Eclipse Distribution License is available at
+ http://www.eclipse.org/org/documents/edl-v10.php.
+
+ Contributors:
+
+ Sam Padgett - initial API and implementation
+ Michael Fiedler - adapted for OSLC4J
+ -->
+<%@ page contentType="text/html" language="java" pageEncoding="UTF-8" %>
+<%@ page import="java.net.*,java.util.*,java.text.SimpleDateFormat" %>
+<%@ page import="org.eclipse.lyo.oslc4j.bugzilla.resources.BugzillaChangeRequest" %>
+<%@ page import="org.eclipse.lyo.oslc4j.bugzilla.resources.Person" %>
+
+
+<%
+BugzillaChangeRequest changeRequest = (BugzillaChangeRequest)request.getAttribute("changeRequest");
+String bugzillaUri = (String) request.getAttribute("bugzillaUri");
+
+Date createdDate = (Date) changeRequest.getCreated();
+SimpleDateFormat formatter = new SimpleDateFormat();
+String created = formatter.format(createdDate);
+Date modifiedDate = (Date) changeRequest.getModified();
+String modified = formatter.format(modifiedDate);
+
+Person assigneePerson = (Person) changeRequest.getContributors().get(0);
+String assignee = "Unknown";
+if (assigneePerson != null)
+ assignee = assigneePerson.getMbox();
+%>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+<title>Change Request: <%= changeRequest.getTitle() %>(<%= changeRequest.getIdentifier() %>))</title>
+<link href="<%= bugzillaUri %>/skins/standard/global.css" rel="stylesheet" type="text/css">
+<link href="<%= bugzillaUri %>/skins/standard/index.css" rel="stylesheet" type="text/css">
+<link href="<%= bugzillaUri %>/skins/standard/global.css" rel="alternate stylesheet" title="Classic" type="text/css">
+<link href="<%= bugzillaUri %>/skins/standard/index.css" rel="alternate stylesheet" title="Classic" type="text/css">
+<link href="<%= bugzillaUri %>/skins/contrib/Dusk/global.css" rel="stylesheet" title="Dusk" type="text/css">
+<link href="<%= bugzillaUri %>/skins/contrib/Dusk/index.css" rel="stylesheet" title="Dusk" type="text/css">
+<link href="<%= bugzillaUri %>/skins/custom/global.css" rel="stylesheet" type="text/css">
+<link href="<%= bugzillaUri %>/skins/custom/index.css" rel="stylesheet" type="text/css">
+<link rel="shortcut icon" href="<%= bugzillaUri %>/images/favicon.ico">
+<style type="text/css">
+body {
+ background: #FFFFFF;
+ padding: 0;
+}
+
+td {
+ padding-right: 5px;
+ min-width: 175px;
+}
+
+th {
+ padding-right: 5px;
+ text-align: right;
+}
+</style>
+</head>
+<body>
+ <div id="bugzilla-body">
+<table class="edit_form">
+ <tr>
+ <th>Status:</th>
+ <td><%= changeRequest.getStatus() %></td>
+ <th>Product:</th>
+ <td><%= changeRequest.getProduct() %></td>
+ </tr>
+
+ <tr>
+ <th>Assignee:</th>
+ <td><%= assignee %></td>
+ <th>Component:</th>
+ <td><%= changeRequest.getComponent() %></td>
+ </tr>
+
+ <tr>
+ <th>Priority:</th>
+ <td><%= changeRequest.getPriority() %></td>
+ <th>Version:</th>
+ <td><%= changeRequest.getVersion() %></td>
+ </tr>
+
+ <tr>
+ <th>Reported:</th>
+ <td><%= created %></td>
+ <th>Modified:</th>
+ <td><%= modified %></td>
+ </tr>
+</table>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_selector.jsp b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_selector.jsp
new file mode 100644
index 0000000..2778908
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/changerequest_selector.jsp
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<%--
+ Copyright (c) 2011, 2012 IBM Corporation.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+
+ The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ and the Eclipse Distribution License is available at
+ http://www.eclipse.org/org/documents/edl-v10.php.
+
+ Contributors:
+
+ Sam Padgett - initial API and implementation
+ Michael Fiedler - adapted for OSLC4J
+--%>
+<%@ page contentType="text/html" language="java" pageEncoding="UTF-8" %>
+<%@ page import="com.j2bugzilla.base.*" %>
+
+<%
+ int productId = (Integer) request.getAttribute("productId");
+ String bugzillaUri = (String) request.getAttribute("bugzillaUri");
+ String selectionUri = (String) request.getAttribute("selectionUri");
+%>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+<title>Bugzilla OSLC Adapter: Resource Selector</title>
+<link href="<%=bugzillaUri%>/skins/standard/global.css" rel="stylesheet" type="text/css">
+<link href="<%=bugzillaUri%>/skins/standard/index.css" rel="stylesheet" type="text/css">
+<link href="<%=bugzillaUri%>/skins/standard/global.css" rel="alternate stylesheet" title="Classic" type="text/css">
+<link href="<%=bugzillaUri%>/skins/standard/index.css" rel="alternate stylesheet" title="Classic" type="text/css">
+<link href="<%=bugzillaUri%>/skins/contrib/Dusk/global.css" rel="stylesheet" title="Dusk" type="text/css">
+<link href="<%=bugzillaUri%>/skins/contrib/Dusk/index.css" rel="stylesheet" title="Dusk" type="text/css">
+<link href="<%=bugzillaUri%>/skins/custom/global.css" rel="stylesheet" type="text/css">
+<link href="<%=bugzillaUri%>/skins/custom/index.css" rel="stylesheet" type="text/css">
+<link rel="shortcut icon" href="<%=bugzillaUri%>/images/favicon.ico">
+
+<script type="text/javascript" src="../../../bugzilla.js"></script>
+
+</head>
+<body style="padding: 10px;">
+ <%-- Padding --%>
+ <div id="bugzilla-body">
+
+ <p id="searchMessage">Find a specific bug by entering words that describe it.</p>
+
+ <p id="loadingMessage" style="display: none;">Bugzilla is pondering your
+ search. Please stand by ...</p>
+
+ <div>
+ <input type="search" style="width: 335px" id="searchTerms" placeholder="Enter search terms" autofocus>
+ <button type="button"
+ onclick="search( '<%= selectionUri %>' )">Search</button>
+ </div>
+
+ <div style="margin-top: 5px;">
+ <select id="results" size="10" style="width: 400px"></select>
+ </div>
+
+ <div style="width: 400px; margin-top: 5px;">
+ <button style="float: right;" type="button"
+ onclick="javascript: cancel()">Cancel</button>
+ <button style="float: right;" type="button"
+ onclick="javascript: select();">OK</button>
+ </div>
+
+ <%-- So the buttons don't float outside the content area. --%>
+ <div style="clear: both;"></div>
+
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/rootservices_rdfxml.jsp b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/rootservices_rdfxml.jsp
new file mode 100644
index 0000000..2625727
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/rootservices_rdfxml.jsp
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<%--
+ Copyright (c) 2011, 2013 IBM Corporation.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+
+ The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ and the Eclipse Distribution License is available at
+ http://www.eclipse.org/org/documents/edl-v10.php.
+
+ Contributors:
+
+ Sam Padgett - initial API and implementation
+ Michael Fiedler - adapted for OSLC4J
+--%>
+<%@ page contentType="application/rdf+xml" language="java" pageEncoding="UTF-8" %>
+<%
+String baseUri = (String) request.getAttribute("baseUri");
+String catalogUri = (String) request.getAttribute("catalogUri");
+String oauthDomain = (String) request.getAttribute("oauthDomain");
+%>
+<!-- Jazz Root Services, see:
+ https://jazz.net/wiki/bin/view/Main/RootServicesSpec
+ https://jazz.net/wiki/bin/view/Main/RootServicesSpecAddendum2
+ -->
+<rdf:Description rdf:about="<%= baseUri + "/rootservices" %>"
+ xmlns:bugz="http://www.bugzilla.org/rdf#"
+ xmlns:trs="http://jazz.net/ns/trs#"
+ xmlns:oslc_cm="http://open-services.net/xmlns/cm/1.0/"
+ xmlns:dcterms="http://purl.org/dc/terms/"
+ xmlns:jfs="http://jazz.net/xmlns/prod/jazz/jfs/1.0/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+
+ <dcterms:title>OSLC-CM Adapter/Bugzilla Jazz Root Services</dcterms:title>
+ <oslc_cm:cmServiceProviders rdf:resource="<%= catalogUri %>" />
+ <jfs:oauthRealmName>Bugzilla</jfs:oauthRealmName>
+ <jfs:oauthDomain><%= oauthDomain %></jfs:oauthDomain>
+ <jfs:oauthRequestConsumerKeyUrl rdf:resource="<%= baseUri + "/oauth/requestKey" %>" />
+ <jfs:oauthApprovalModuleUrl rdf:resource="<%= baseUri + "/oauth/approveKey" %>" />
+ <jfs:oauthRequestTokenUrl rdf:resource="<%= baseUri + "/oauth/requestToken" %>"/>
+ <jfs:oauthUserAuthorizationUrl rdf:resource="<%= baseUri + "/oauth/authorize" %>" />
+ <jfs:oauthAccessTokenUrl rdf:resource="<%= baseUri + "/oauth/accessToken" %>"/>
+<%-- Added in Lab 1.1 --%>
+ <!-- Bugzilla Tracked Resource Set Provider -->
+ <bugz:trackedResourceSetProvider>
+ <trs:TrackedResourceSetProvider>
+ <trs:trackedResourceSet rdf:resource="<%= baseUri + "/trs" %>" />
+ </trs:TrackedResourceSetProvider>
+ </bugz:trackedResourceSetProvider>
+</rdf:Description>
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/serviceprovider_html.jsp b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/serviceprovider_html.jsp
new file mode 100644
index 0000000..5efaf0f
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/serviceprovider_html.jsp
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<%--
+ Copyright (c) 2011, 2012 IBM Corporation.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+
+ The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ and the Eclipse Distribution License is available at
+ http://www.eclipse.org/org/documents/edl-v10.php.
+
+ Contributors:
+
+ Sam Padgett - initial API and implementation
+ Michael Fiedler - adapted for OSLC4J
+--%>
+<%@ page contentType="text/html" language="java" pageEncoding="UTF-8" %>
+<%@ page import="java.net.URI" %>
+<%@ page import="org.eclipse.lyo.oslc4j.core.model.Service" %>
+<%@ page import="org.eclipse.lyo.oslc4j.core.model.ServiceProvider" %>
+<%@ page import="org.eclipse.lyo.oslc4j.core.model.Dialog" %>
+<%@ page import="org.eclipse.lyo.oslc4j.core.model.CreationFactory" %>
+<%@ page import="org.eclipse.lyo.oslc4j.core.model.ResourceShape" %>
+<%@ page import="org.eclipse.lyo.oslc4j.core.model.QueryCapability" %>
+
+
+<%
+String bugzillaUri = (String) request.getAttribute("bugzillaUri");
+Service service = (Service)request.getAttribute("service");
+ServiceProvider serviceProvider = (ServiceProvider)request.getAttribute("serviceProvider");
+
+//OSLC Dialogs
+Dialog [] selectionDialogs = service.getSelectionDialogs();
+String selectionDialog = selectionDialogs[0].getDialog().toString();
+Dialog [] creationDialogs = service.getCreationDialogs();
+String creationDialog = creationDialogs[0].getDialog().toString();
+
+//OSLC CreationFactory and shape
+CreationFactory [] creationFactories = service.getCreationFactories();
+String creationFactory = creationFactories[0].getCreation().toString();
+URI[] creationShapes = creationFactories[0].getResourceShapes();
+String creationShape = creationShapes[0].toString();
+
+//OSLC QueryCapability and shape
+QueryCapability [] queryCapabilities= service.getQueryCapabilities();
+String queryCapability = queryCapabilities[0].getQueryBase().toString();
+String queryShape = queryCapabilities[0].getResourceShape().toString();
+
+
+%>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+ <title>Bugzilla OSLC Adapter: Service Provider for <%= serviceProvider.getTitle() + "(" + serviceProvider.getIdentifier() + ")" %></title>
+ <link href="<%= bugzillaUri %>/skins/standard/global.css" rel="stylesheet" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/standard/index.css" rel="stylesheet" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/standard/global.css" rel="alternate stylesheet" title="Classic" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/standard/index.css" rel="alternate stylesheet" title="Classic" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/contrib/Dusk/global.css" rel="stylesheet" title="Dusk" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/contrib/Dusk/index.css" rel="stylesheet" title="Dusk" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/custom/global.css" rel="stylesheet" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/custom/index.css" rel="stylesheet" type="text/css">
+ <link rel="shortcut icon" href="<%= bugzillaUri %>/images/favicon.ico">
+ </head>
+ <body onload="">
+
+ <div id="header">
+ <div id="banner"></div>
+ <table border="0" cellspacing="0" cellpadding="0" id="titles">
+ <tr>
+ <td id="title">
+ <p>
+ Bugzilla OSLC Adapter: Service Provider
+ </p>
+ </td>
+ <td id="information">
+ <p class="header_addl_info">
+ version 0.1
+ </p>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <div id="bugzilla-body">
+ <div id="page-index">
+
+ <img src="../../images/resources/bugzilla.gif" alt="icon" width="80" height="80" />
+
+ <h1>Service Provider for <%= serviceProvider.getTitle() + "(" + serviceProvider.getIdentifier() + ")" %></h1>
+
+ <p>Enables navigation to OSLC-CM Resource Creator and Selector Dialogs</p>
+
+ <table>
+ <tr>
+ <td><b>This document</b>:</td>
+ <td><a href="<%= serviceProvider.getAbout() %>">
+ <%= serviceProvider.getAbout() %></a></td>
+ </tr>
+ <tr>
+ <td><b>Bugzilla</b>:</td>
+ <td><a href="<%= bugzillaUri %>"><%= bugzillaUri %></a></td>
+ </tr>
+ <tr>
+ <td><b>Adapter Publisher</b>:</td>
+ <td>Eclipse Lyo</td>
+ </tr>
+ <tr>
+ <td><b>Adapter Identity</b>:</td>
+ <td>org.eclipse.lyo.oslc4j.bugzilla.test</td>
+ </tr>
+ </table>
+
+ <h2>OSLC-CM Resource Selector Dialog</h2>
+ <p><a href="<%= selectionDialog %>">
+ <%= selectionDialog %></a></p>
+
+ <h2>OSLC-CM Resource Creator Dialog</h2>
+ <p><a href="<%= creationDialog %>">
+ <%= creationDialog %></a></p>
+
+ <h2>OSLC-CM Resource Creation Factory and Resource Shape</h2>
+ <p><a href="<%= creationFactory %>">
+ <%= creationFactory %></a></p>
+ <p><a href="<%= creationShape %>">
+ <%= creationShape %></a></p>
+
+ <h2>OSLC-CM Resource Query Capability and Resource Shape</h2>
+ <p><a href="<%= queryCapability %>">
+ <%= queryCapability %></a></p>
+ <p><a href="<%= queryShape %>">
+ <%= queryShape %></a></p>
+ </div>
+ </div>
+
+ <div id="footer">
+ <div class="intro"></div>
+ <div class="outro">
+ <div style="margin: 0 1em 1em 1em; line-height: 1.6em; text-align: left">
+ <b>OSLC Tools Adapter Server 0.1</b> brought to you by <a href="http://eclipse.org/lyo">Eclipse Lyo</a><br>
+ </div>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/serviceprovidercatalog_html.jsp b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/serviceprovidercatalog_html.jsp
new file mode 100644
index 0000000..c088eec
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/cm/serviceprovidercatalog_html.jsp
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<%--
+ Copyright (c) 2011, 2012 IBM Corporation.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+
+ The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ and the Eclipse Distribution License is available at
+ http://www.eclipse.org/org/documents/edl-v10.php.
+
+ Contributors:
+
+ Sam Padgett - initial API and implementation
+ Michael Fiedler - OSLC4J adaptation
+--%>
+<%@ page contentType="text/html" language="java" pageEncoding="UTF-8" %>
+<%@ page import="org.eclipse.lyo.oslc4j.core.model.ServiceProviderCatalog" %>
+<%@ page import="org.eclipse.lyo.oslc4j.core.model.ServiceProvider" %>
+<%
+String bugzillaUri = (String) request.getAttribute("bugzillaUri");
+ServiceProviderCatalog catalog = (ServiceProviderCatalog)request.getAttribute("catalog");
+%>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+ <title>Bugzilla OSLC Adapter: Service Provider Catalog</title>
+ <link href="<%= bugzillaUri %>/skins/standard/global.css" rel="stylesheet" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/standard/index.css" rel="stylesheet" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/standard/global.css" rel="alternate stylesheet" title="Classic" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/standard/index.css" rel="alternate stylesheet" title="Classic" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/contrib/Dusk/global.css" rel="stylesheet" title="Dusk" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/contrib/Dusk/index.css" rel="stylesheet" title="Dusk" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/custom/global.css" rel="stylesheet" type="text/css">
+ <link href="<%= bugzillaUri %>/skins/custom/index.css" rel="stylesheet" type="text/css">
+ <link rel="shortcut icon" href="<%= bugzillaUri %>/images/favicon.ico">
+ </head>
+ <body onload="">
+
+ <div id="header">
+ <div id="banner"></div>
+ <table border="0" cellspacing="0" cellpadding="0" id="titles">
+ <tr>
+ <td id="title">
+ <p>
+ Bugzilla OSLC Adapter: Service Provider Catalog
+ </p>
+ </td>
+ <td id="information">
+ <p class="header_addl_info">
+ version 0.1
+ </p>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <div id="bugzilla-body">
+ <div id="page-index">
+
+ <img src="../../images/resources/bugzilla.gif" alt="icon" width="80" height="80" />
+
+ <h1>Service Provider Catalog</h1>
+
+ <p>Enables navigation to Service Provider for each Product against which bugs may be reported.</p>
+
+ <table>
+ <tr>
+ <td><b>This document</b>:</td>
+ <td><a href="<%= catalog.getAbout() %>">
+ <%= catalog.getAbout().toString() %>
+ </a></td>
+ </tr>
+ <tr>
+ <td><b>Bugzilla</b>:</td>
+ <td><a href="<%= bugzillaUri %>"><%= bugzillaUri %></a></td>
+ </tr>
+ <tr>
+ <td><b>Adapter Publisher</b>:</td>
+ <td>OSLC Tools Project</td>
+ </tr>
+ <tr>
+ <td><b>Adapter Identity</b>:</td>
+ <td>org.eclipse.lyo.samples.bugzilla.test</td>
+ </tr>
+ </table>
+
+ <h2>Service Providers</h2>
+
+ <% for (ServiceProvider s : catalog.getServiceProviders()) { %>
+ <h3>Service Provider for Product <%= s.getTitle() %></h3>
+ <p><a href="<%= s.getAbout() %>">
+ <%= s.getAbout() %></a></p>
+ <% } %>
+
+ </div>
+ </div>
+
+ <div id="footer">
+ <div class="intro"></div>
+ <div class="outro">
+ <div style="margin: 0 1em 1em 1em; line-height: 1.6em; text-align: left">
+ <b>OSLC Tools Adapter Server 0.1</b> brought to you by <a href="http://eclipse.org/lyo">Eclipse Lyo</a><br>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/images/resources/bugzilla.gif b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/images/resources/bugzilla.gif
new file mode 100644
index 0000000..16973a4
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/images/resources/bugzilla.gif
Binary files differ
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/images/resources/oslc.png b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/images/resources/oslc.png
new file mode 100644
index 0000000..81015ab
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/images/resources/oslc.png
Binary files differ
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/images/resources/oslcLg.png b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/images/resources/oslcLg.png
new file mode 100644
index 0000000..3185789
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/images/resources/oslcLg.png
Binary files differ
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/index.jsp b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/index.jsp
new file mode 100644
index 0000000..6f07b72
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/main/webapp/index.jsp
@@ -0,0 +1,5 @@
+<html>
+<body>
+<h2>Hello World!</h2>
+</body>
+</html>
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/test/java/.gitignore b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/test/java/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/test/java/.gitignore
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/test/launches/Launch TRS Reference App for Bugzilla.launch b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/test/launches/Launch TRS Reference App for Bugzilla.launch
new file mode 100644
index 0000000..3fffbaf
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/test/launches/Launch TRS Reference App for Bugzilla.launch
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?><launchConfiguration type="org.eclipse.m2e.Maven2LaunchConfigurationType">
+<booleanAttribute key="M2_DEBUG_OUTPUT" value="false"/>
+<stringAttribute key="M2_GOALS" value="jetty:run"/>
+<booleanAttribute key="M2_NON_RECURSIVE" value="false"/>
+<booleanAttribute key="M2_OFFLINE" value="false"/>
+<stringAttribute key="M2_PROFILES" value=""/>
+<listAttribute key="M2_PROPERTIES"/>
+<stringAttribute key="M2_RUNTIME" value="EMBEDDED"/>
+<booleanAttribute key="M2_SKIP_TESTS" value="false"/>
+<booleanAttribute key="M2_UPDATE_SNAPSHOTS" value="false"/>
+<booleanAttribute key="M2_WORKSPACE_RESOLUTION" value="false"/>
+<stringAttribute key="org.eclipse.debug.core.source_locator_id" value="org.eclipse.m2e.launching.MavenSourceLocator"/>
+<stringAttribute key="org.eclipse.debug.core.source_locator_memento" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;sourceLookupDirector&gt;&#13;&#10;&lt;sourceContainers duplicates=&quot;false&quot;&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&amp;lt;javaProject name=&amp;quot;OSLC4J&amp;quot;/&amp;gt;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&amp;lt;javaProject name=&amp;quot;org.eclipse.lyo.oslc4j.bugzilla.trs&amp;quot;/&amp;gt;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&amp;lt;javaProject name=&amp;quot;OSLC4JJenaProvider&amp;quot;/&amp;gt;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&amp;lt;javaProject name=&amp;quot;OSLC4JJson4JProvider&amp;quot;/&amp;gt;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&amp;lt;javaProject name=&amp;quot;OSLC4JWink&amp;quot;/&amp;gt;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&amp;lt;javaProject name=&amp;quot;org.eclipse.lyo.server.oauth.consumerstore&amp;quot;/&amp;gt;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&amp;lt;javaProject name=&amp;quot;org.eclipse.lyo.server.oauth.core&amp;quot;/&amp;gt;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&amp;lt;javaProject name=&amp;quot;org.eclipse.lyo.server.oauth.webapp&amp;quot;/&amp;gt;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&amp;lt;default/&amp;gt;&quot; typeId=&quot;org.eclipse.debug.core.containerType.default&quot;/&gt;&#13;&#10;&lt;/sourceContainers&gt;&#13;&#10;&lt;/sourceLookupDirector&gt;"/>
+<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:/org.eclipse.lyo.oslc4j.bugzilla.trs}"/>
+</launchConfiguration> \ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.bugzilla.trs/src/test/resources/.gitignore b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/test/resources/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.bugzilla.trs/src/test/resources/.gitignore