Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoberto E. Escobar2014-05-30 18:07:08 +0000
committerRoberto E. Escobar2014-05-31 00:40:10 +0000
commit55ed5debef6a0dfbb31e96e79d7e85452c8cb3e6 (patch)
treedaaa217b8cbc91e7cac7e6d9d066cf5aaf74c418 /plugins/org.eclipse.osee.jaxrs.server
parent4f99b6fc8ba615602794f04029e7a81426488272 (diff)
downloadorg.eclipse.osee-55ed5debef6a0dfbb31e96e79d7e85452c8cb3e6.tar.gz
org.eclipse.osee-55ed5debef6a0dfbb31e96e79d7e85452c8cb3e6.tar.xz
org.eclipse.osee-55ed5debef6a0dfbb31e96e79d7e85452c8cb3e6.zip
refactor: Rename rest.admin to jaxrs.server
Diffstat (limited to 'plugins/org.eclipse.osee.jaxrs.server')
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/.classpath7
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/.project33
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/META-INF/MANIFEST.MF36
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/OSGI-INF/jaxrs.application.manager.xml23
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/build.properties5
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/pom.xml34
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/BundleHttpContext.java55
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/BundleWadlGeneratorConfig.java123
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/GenericExceptionMapper.java97
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/ObjectProvider.java20
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestComponentFactory.java86
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestResourceConcatenator.java106
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServiceUtils.java72
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServletContainer.java113
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServletManager.java175
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServletRegistry.java138
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/SecurityContextProvider.java23
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/filters/SecureResourceFilterFactory.java61
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/filters/SecurityContextFilter.java53
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/filters/SecurityContextProviderImpl.java138
-rw-r--r--plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/resources/ApplicationsResource.java73
21 files changed, 1471 insertions, 0 deletions
diff --git a/plugins/org.eclipse.osee.jaxrs.server/.classpath b/plugins/org.eclipse.osee.jaxrs.server/.classpath
new file mode 100644
index 00000000000..ad32c83a788
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.osee.jaxrs.server/.project b/plugins/org.eclipse.osee.jaxrs.server/.project
new file mode 100644
index 00000000000..9a67a65965e
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.osee.jaxrs.server</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ds.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.osee.jaxrs.server/META-INF/MANIFEST.MF b/plugins/org.eclipse.osee.jaxrs.server/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..423be072bd9
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/META-INF/MANIFEST.MF
@@ -0,0 +1,36 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: OSEE JAX-RS Server (Incubation)
+Bundle-SymbolicName: org.eclipse.osee.jaxrs.server
+Bundle-Version: 0.17.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Service-Component: OSGI-INF/*.xml
+Import-Package: com.google.common.io,
+ com.sun.jersey.api.container.filter.servlet;version="1.18.0",
+ com.sun.jersey.api.core,
+ com.sun.jersey.api.model;version="1.18.0",
+ com.sun.jersey.api.wadl.config,
+ com.sun.jersey.server.wadl,
+ com.sun.jersey.server.wadl.generators,
+ com.sun.jersey.server.wadl.generators.resourcedoc,
+ com.sun.jersey.server.wadl.generators.resourcedoc.model,
+ com.sun.jersey.server.wadl.generators.resourcedoc.xhtml,
+ com.sun.jersey.spi.container;version="1.18.0",
+ com.sun.jersey.spi.container.servlet,
+ javax.servlet;version="2.5.0",
+ javax.servlet.http;version="2.5.0",
+ javax.ws.rs,
+ javax.ws.rs.core,
+ javax.ws.rs.ext,
+ org.eclipse.osee.executor.admin,
+ org.eclipse.osee.authorization.admin,
+ org.eclipse.osee.framework.jdk.core.type,
+ org.eclipse.osee.framework.jdk.core.util,
+ org.eclipse.osee.logger,
+ org.eclipse.osee.jaxrs,
+ org.osgi.framework,
+ org.osgi.service.http
+Bundle-Vendor: Eclipse Open System Engineering Environment
+Require-Bundle: org.codehaus.jackson.core,
+ org.codehaus.jackson.jaxrs,
+ org.codehaus.jackson.mapper
diff --git a/plugins/org.eclipse.osee.jaxrs.server/OSGI-INF/jaxrs.application.manager.xml b/plugins/org.eclipse.osee.jaxrs.server/OSGI-INF/jaxrs.application.manager.xml
new file mode 100644
index 00000000000..ceeb783b31d
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/OSGI-INF/jaxrs.application.manager.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="start" deactivate="stop" enabled="true" immediate="true">
+ <implementation class="org.eclipse.osee.jaxrs.server.internal.RestServletManager"/>
+
+ <reference interface="org.osgi.service.http.HttpService" name="HttpService"
+ cardinality="1..1"
+ policy="static"
+ bind="setHttpService" />
+
+ <reference interface="org.eclipse.osee.logger.Log" name="Log"
+ cardinality="1..1"
+ policy="static"
+ bind="setLogger" />
+
+
+ <reference interface="javax.ws.rs.core.Application" name="Application"
+ cardinality="1..n"
+ policy="dynamic"
+ bind="addApplication"
+ unbind="removeApplication" />
+ <reference bind="setExecutorAdmin" cardinality="1..1" interface="org.eclipse.osee.executor.admin.ExecutorAdmin" name="ExecutorAdmin" policy="static"/>
+ <reference bind="setAuthorizationAdmin" cardinality="1..1" interface="org.eclipse.osee.authorization.admin.AuthorizationAdmin" name="AuthorizationAdmin" policy="static"/>
+</scr:component>
diff --git a/plugins/org.eclipse.osee.jaxrs.server/build.properties b/plugins/org.eclipse.osee.jaxrs.server/build.properties
new file mode 100644
index 00000000000..6210e849b59
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/build.properties
@@ -0,0 +1,5 @@
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ OSGI-INF/
+source.. = src/
diff --git a/plugins/org.eclipse.osee.jaxrs.server/pom.xml b/plugins/org.eclipse.osee.jaxrs.server/pom.xml
new file mode 100644
index 00000000000..5dc7217d890
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/pom.xml
@@ -0,0 +1,34 @@
+<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>
+
+ <parent>
+ <groupId>org.eclipse.osee</groupId>
+ <artifactId>org.eclipse.osee.x.core.parent</artifactId>
+ <version>0.17.0-SNAPSHOT</version>
+ <relativePath>../../plugins/org.eclipse.osee.x.core.parent</relativePath>
+ </parent>
+
+ <artifactId>org.eclipse.osee.jaxrs.server</artifactId>
+ <packaging>eclipse-plugin</packaging>
+ <name>OSEE JAX-RS Server - (Incubation)</name>
+
+ <build>
+ <!-- workaround for https://issues.sonatype.org/browse/TYCHO-168 -->
+ <resources>
+ <resource>
+ <directory>src</directory>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>tycho-source-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project> \ No newline at end of file
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/BundleHttpContext.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/BundleHttpContext.java
new file mode 100644
index 00000000000..6169f91ef4a
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/BundleHttpContext.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal;
+
+import java.net.URL;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpContext;
+
+/**
+ * @author Roberto E. Escobar
+ */
+public class BundleHttpContext implements HttpContext {
+
+ private final ObjectProvider<Iterable<Bundle>> bundlesProvider;
+
+ public BundleHttpContext(ObjectProvider<Iterable<Bundle>> bundlesProvider) {
+ this.bundlesProvider = bundlesProvider;
+ }
+
+ @Override
+ public URL getResource(String path) {
+ // find first bundle that has an entry for the path
+ URL toReturn = null;
+ Iterable<Bundle> bundles = bundlesProvider.get();
+ for (Bundle bundle : bundles) {
+ toReturn = bundle.getEntry(path);
+ if (toReturn != null) {
+ return toReturn;
+ }
+ }
+ return toReturn;
+ }
+
+ @Override
+ public String getMimeType(String name) {
+ return null;
+ }
+
+ @Override
+ public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) {
+ // Assume the container has already performed authentication
+ return true;
+ }
+
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/BundleWadlGeneratorConfig.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/BundleWadlGeneratorConfig.java
new file mode 100644
index 00000000000..3911c64af50
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/BundleWadlGeneratorConfig.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+import org.eclipse.osee.framework.jdk.core.util.Lib;
+import org.eclipse.osee.logger.Log;
+import org.osgi.framework.Bundle;
+import com.google.common.io.InputSupplier;
+import com.sun.jersey.api.wadl.config.WadlGeneratorConfig;
+import com.sun.jersey.api.wadl.config.WadlGeneratorDescription;
+import com.sun.jersey.server.wadl.generators.WadlGeneratorApplicationDoc;
+import com.sun.jersey.server.wadl.generators.WadlGeneratorGrammarsSupport;
+import com.sun.jersey.server.wadl.generators.resourcedoc.WadlGeneratorResourceDocSupport;
+
+/**
+ * @author Roberto E. Escobar
+ */
+public class BundleWadlGeneratorConfig extends WadlGeneratorConfig {
+
+ private final Log logger;
+ private final ObjectProvider<Iterable<Bundle>> provider;
+
+ public BundleWadlGeneratorConfig(Log logger, ObjectProvider<Iterable<Bundle>> provider) {
+ this.logger = logger;
+ this.provider = provider;
+ }
+
+ public boolean hasExtendedWadl() {
+ boolean result = false;
+ Iterable<Bundle> bundles = provider.get();
+ for (Bundle bundle : bundles) {
+ result = hasExtendedWadl(bundle);
+ if (result) {
+ break;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public List<WadlGeneratorDescription> configure() {
+ List<WadlGeneratorDescription> toReturn;
+
+ InputStream appDocsStream = null;
+ InputStream grammarsStream = null;
+ InputStream resourceDocStream = null;
+ try {
+ appDocsStream = getAsInputStream("REST-INF/application-doc.xml", "applicationDocs");
+ grammarsStream = getAsInputStream("REST-INF/application-grammars.xml", "grammars");
+ resourceDocStream = getAsInputStream("REST-INF/resourcedoc.xml", "resourceDoc");
+
+ toReturn = generator(WadlGeneratorApplicationDoc.class) //
+ .prop("applicationDocsStream", appDocsStream) //
+ .generator(WadlGeneratorGrammarsSupport.class) //
+ .prop("grammarsStream", grammarsStream) //
+ .generator(WadlGeneratorResourceDocSupport.class) //
+ .prop("resourceDocStream", resourceDocStream) //
+ .descriptions();
+ } catch (Exception ex) {
+ logger.error(ex, "Error generating wadl");
+ toReturn = Collections.emptyList();
+ } finally {
+ Lib.close(appDocsStream);
+ Lib.close(grammarsStream);
+ Lib.close(resourceDocStream);
+ }
+ return toReturn;
+ }
+
+ private static InputSupplier<InputStream> newSupplier(final URL url) {
+ return new InputSupplier<InputStream>() {
+ @Override
+ public InputStream getInput() throws IOException {
+ return url.openStream();
+ }
+ };
+ }
+
+ private InputStream getAsInputStream(String path, String xmlRoot) throws Exception {
+ RestResourceConcatenator concat = new RestResourceConcatenator();
+ concat.initialize(xmlRoot);
+ Iterable<Bundle> bundles = provider.get();
+ for (Bundle bundle : bundles) {
+ if (hasExtendedWadl(bundle)) {
+ URL url = bundle.getResource(path);
+ concat.addResource(newSupplier(url));
+ }
+ }
+ return concat.getAsInputStream();
+ }
+
+ private boolean hasEntries(Bundle bundle, String... paths) {
+ // if you don't pass in any paths, this will return true
+ for (String path : paths) {
+ if (!hasEntry(bundle, path)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean hasExtendedWadl(Bundle bundle) {
+ return hasEntries(bundle, "REST-INF/application-doc.xml", "REST-INF/application-grammars.xml",
+ "REST-INF/resourcedoc.xml");
+ }
+
+ private boolean hasEntry(Bundle bundle, String path) {
+ return bundle.getEntry(path) != null;
+ }
+}
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/GenericExceptionMapper.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/GenericExceptionMapper.java
new file mode 100644
index 00000000000..941a298f2f8
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/GenericExceptionMapper.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.Response.Status.Family;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+import org.eclipse.osee.jaxrs.ErrorResponse;
+import org.eclipse.osee.jaxrs.OseeWebApplicationException;
+import org.eclipse.osee.logger.Log;
+
+/**
+ * @author Roberto E. Escobar
+ */
+@Provider
+public class GenericExceptionMapper implements ExceptionMapper<Throwable> {
+
+ private static final String SEE_HTTP_STATUS_CODES = "See HTTP Status codes";
+ private static final String INTERNAL_SERVER_ERROR_TYPE = "Internal Server Error";
+ private static final String APPLICATION_EXCEPTION_TYPE = "Web Application Exception";
+ private static final String OSEE_APPLICATION_EXCEPTION_TYPE = "Osee Web Application Exception";
+
+ private final Log logger;
+
+ public GenericExceptionMapper(Log logger) {
+ super();
+ this.logger = logger;
+ }
+
+ @Override
+ public Response toResponse(Throwable throwable) {
+ boolean isError = false;
+ String logMessage;
+
+ OseeWebApplicationException exception;
+ if (throwable instanceof OseeWebApplicationException) {
+ logMessage = OSEE_APPLICATION_EXCEPTION_TYPE;
+ exception = ((OseeWebApplicationException) throwable);
+ } else if (throwable instanceof WebApplicationException) {
+ logMessage = APPLICATION_EXCEPTION_TYPE;
+ WebApplicationException webAppException = ((WebApplicationException) throwable);
+ Response response = webAppException.getResponse();
+ int statusCode = response.getStatus();
+ String message = webAppException.getMessage();
+
+ javax.ws.rs.core.Response.StatusType status = Status.fromStatusCode(statusCode);
+ if (status == null) {
+ status = newStatusType(statusCode, Family.SERVER_ERROR, SEE_HTTP_STATUS_CODES);
+ }
+ exception = new OseeWebApplicationException(throwable, status, message);
+ } else {
+ isError = true;
+ logMessage = INTERNAL_SERVER_ERROR_TYPE;
+ exception = new OseeWebApplicationException(throwable, Status.INTERNAL_SERVER_ERROR);
+ }
+
+ ErrorResponse errorResponse = exception.getErrorResponse();
+ if (isError) {
+ logger.error(throwable, "%s - [%s]", logMessage, errorResponse);
+ } else {
+ logger.info(throwable, "%s - [%s]", logMessage, errorResponse);
+ }
+ return exception.getResponse();
+ }
+
+ private javax.ws.rs.core.Response.StatusType newStatusType(final int code, final Family family, final String reason) {
+ return new javax.ws.rs.core.Response.StatusType() {
+
+ @Override
+ public int getStatusCode() {
+ return code;
+ }
+
+ @Override
+ public Family getFamily() {
+ return family;
+ }
+
+ @Override
+ public String getReasonPhrase() {
+ return reason;
+ }
+
+ };
+ }
+}
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/ObjectProvider.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/ObjectProvider.java
new file mode 100644
index 00000000000..99aaf392c7f
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/ObjectProvider.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal;
+
+/**
+ * @author Roberto E. Escobar
+ */
+public interface ObjectProvider<T> {
+
+ T get();
+
+}
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestComponentFactory.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestComponentFactory.java
new file mode 100644
index 00000000000..5870d61e691
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestComponentFactory.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import org.eclipse.osee.jaxrs.server.internal.filters.SecureResourceFilterFactory;
+import org.eclipse.osee.jaxrs.server.internal.filters.SecurityContextFilter;
+import org.eclipse.osee.jaxrs.server.internal.resources.ApplicationsResource;
+import org.eclipse.osee.logger.Log;
+import org.osgi.framework.Bundle;
+import com.sun.jersey.api.core.DefaultResourceConfig;
+import com.sun.jersey.api.core.ResourceConfig;
+import com.sun.jersey.spi.container.ResourceFilterFactory;
+import com.sun.jersey.spi.container.servlet.ServletContainer;
+
+/**
+ * @author Roberto E. Escobar
+ */
+public class RestComponentFactory {
+ private final Log logger;
+ private final SecurityContextFilter securityContextFilter;
+
+ private List<Object> defaultSingletonResources;
+
+ public RestComponentFactory(Log logger, SecurityContextFilter securityContextFilter) {
+ super();
+ this.logger = logger;
+ this.securityContextFilter = securityContextFilter;
+ }
+
+ public List<ResourceFilterFactory> getResourceFilterFactories() {
+ SecureResourceFilterFactory filterFactory = new SecureResourceFilterFactory(logger, securityContextFilter);
+ return Collections.<ResourceFilterFactory> singletonList(filterFactory);
+ }
+
+ public List<Object> getResourceSingletons() {
+ if (defaultSingletonResources == null) {
+ GenericExceptionMapper exceptionMapper = new GenericExceptionMapper(logger);
+ defaultSingletonResources = Collections.<Object> singletonList(exceptionMapper);
+ }
+ return defaultSingletonResources;
+ }
+
+ public RestServletContainer createContainer(String context) throws Exception {
+ DefaultResourceConfig config = new DefaultResourceConfig();
+
+ for (Object resource : getResourceSingletons()) {
+ config.getSingletons().add(resource);
+ }
+
+ Map<String, Bundle> bundleMap = new ConcurrentHashMap<String, Bundle>();
+ ObjectProvider<Iterable<Bundle>> provider = newBundleProvider(bundleMap);
+ config.getProperties().put(ResourceConfig.PROPERTY_RESOURCE_FILTER_FACTORIES, getResourceFilterFactories());
+
+ BundleHttpContext bundleContext = new BundleHttpContext(provider);
+ BundleWadlGeneratorConfig wadlGenerator = new BundleWadlGeneratorConfig(logger, provider);
+
+ ApplicationsResource resource = new ApplicationsResource(provider);
+ config.getSingletons().add(resource);
+
+ ServletContainer container = new ServletContainer(config);
+ return new RestServletContainer(logger, context, bundleMap, container, config, bundleContext, wadlGenerator);
+ }
+
+ private ObjectProvider<Iterable<Bundle>> newBundleProvider(final Map<String, Bundle> bundleMap) {
+ return new ObjectProvider<Iterable<Bundle>>() {
+
+ @Override
+ public Iterable<Bundle> get() {
+ return bundleMap.values();
+ }
+ };
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestResourceConcatenator.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestResourceConcatenator.java
new file mode 100644
index 00000000000..0e96e54e0f4
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestResourceConcatenator.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.eclipse.osee.framework.jdk.core.type.OseeArgumentException;
+import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
+import org.eclipse.osee.framework.jdk.core.util.Conditions;
+import org.eclipse.osee.framework.jdk.core.util.Lib;
+import com.google.common.io.InputSupplier;
+
+/**
+ * @author David W. Miller
+ */
+public class RestResourceConcatenator {
+ private final Set<String> resources = new HashSet<String>();
+ private String header;
+ private String footer;
+ private Pattern resourcePattern = null;
+
+ public void initialize(String xmlTag) {
+ if (resourcePattern != null) {
+ throw new OseeArgumentException("Already initialized");
+ }
+ validateTag(xmlTag);
+ String regex = String.format("(.*?<%s.*?>)(.+?)(</%s>)", xmlTag, xmlTag);
+
+ resourcePattern = Pattern.compile(regex, Pattern.DOTALL);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s Object: \n contents {%s}\n", this.getClass().getName(), getResources());
+ }
+
+ public void addResource(InputSupplier<? extends InputStream> supplier) throws IOException {
+ Conditions.checkNotNull(supplier, "InputStreamSupplier");
+ InputStream is = null;
+ try {
+ is = supplier.getInput();
+ processResource(Lib.inputStreamToString(is));
+ } finally {
+ Lib.close(is);
+ }
+ }
+
+ public InputStream getAsInputStream() throws UnsupportedEncodingException {
+ if (resources.isEmpty() || header == null || footer == null) {
+ throw new OseeCoreException("Rest resource not ready - no data");
+ }
+ return Lib.stringToInputStream(getResources());
+ }
+
+ public String getResources() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(header);
+ for (String resource : resources) {
+ sb.append(resource);
+ }
+ sb.append(footer);
+ return sb.toString();
+ }
+
+ private void processResource(String input) {
+ Conditions.checkNotNullOrEmpty(input, "bundle resource");
+ Matcher match = resourcePattern.matcher(input);
+ while (match.find()) {
+ if (resources.isEmpty()) {
+ header = match.group(1);
+ footer = match.group(3);
+ }
+ resources.add(match.group(2));
+ }
+ }
+
+ private void validateTag(String xmlTag) {
+
+ Conditions.checkNotNullOrEmpty(xmlTag, "xmlTag");
+ // resources can only have three tags: "resourceDoc", "applicationDocs" or "grammars"
+ boolean valid = false;
+ if (xmlTag.equals("resourceDoc")) {
+ valid = true;
+ } else if (xmlTag.equals("applicationDocs")) {
+ valid = true;
+ } else if (xmlTag.equals("grammars")) {
+ valid = true;
+ }
+ if (!valid) {
+ throw new OseeArgumentException("Invalid resource document tag");
+ }
+ }
+}
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServiceUtils.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServiceUtils.java
new file mode 100644
index 00000000000..cad00f06899
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServiceUtils.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import javax.ws.rs.core.Application;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * @author Roberto E. Escobar
+ */
+public final class RestServiceUtils {
+
+ private RestServiceUtils() {
+ // Utility class
+ }
+
+ public static String getContextName(ServiceReference<?> reference) {
+ String contextName = (String) reference.getProperty("context.name");
+ if (!isValid(contextName)) {
+ contextName = getComponentName(reference);
+ }
+ return normalize(contextName);
+ }
+
+ public static String getComponentName(ServiceReference<?> reference) {
+ return (String) reference.getProperty("component.name");
+ }
+
+ public static void checkValid(Application application) throws Exception {
+ if (application == null) {
+ throw new IllegalStateException("javax.ws.rs.Application service was null");
+ }
+ if (!hasResources(application)) {
+ throw new IllegalStateException("javax.ws.rs.Application had no resources declared");
+ }
+ }
+
+ private static boolean hasResources(Application app) {
+ return !isNullOrEmpty(app.getClasses()) || !isNullOrEmpty(app.getSingletons());
+ }
+
+ private static String normalize(String contextName) {
+ return contextName != null && !contextName.startsWith("/") ? "/" + contextName : contextName;
+ }
+
+ private static boolean isValid(String value) {
+ return value != null && value.length() > 0;
+ }
+
+ private static boolean isNullOrEmpty(Collection<?> collection) {
+ return collection == null || collection.isEmpty();
+ }
+
+ public static Map<String, String> toMap(String componentName, String contextName) {
+ Map<String, String> data = new HashMap<String, String>();
+ data.put("component.name", componentName);
+ data.put("context.name", contextName);
+ return data;
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServletContainer.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServletContainer.java
new file mode 100644
index 00000000000..43e10443624
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServletContainer.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.ws.rs.core.Application;
+import org.eclipse.osee.logger.Log;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpContext;
+import com.sun.jersey.api.core.DefaultResourceConfig;
+import com.sun.jersey.api.core.ResourceConfig;
+import com.sun.jersey.spi.container.servlet.ServletContainer;
+
+/**
+ * @author David W. Miller
+ */
+public class RestServletContainer {
+ private final Map<String, Application> applications = new ConcurrentHashMap<String, Application>();
+
+ private final Log logger;
+ private final String baseContext;
+ private final Map<String, Bundle> bundles;
+ private final ServletContainer container;
+ private final DefaultResourceConfig resourceConfig;
+ private final HttpContext context;
+ private final BundleWadlGeneratorConfig wadl;
+
+ public RestServletContainer(Log logger, String baseContext, Map<String, Bundle> bundles, ServletContainer container, DefaultResourceConfig resourceConfig, HttpContext context, BundleWadlGeneratorConfig wadl) {
+ super();
+ this.logger = logger;
+ this.baseContext = baseContext;
+ this.bundles = bundles;
+ this.container = container;
+ this.resourceConfig = resourceConfig;
+ this.context = context;
+ this.wadl = wadl;
+ }
+
+ public String getContext() {
+ return baseContext;
+ }
+
+ public void addApplication(String key, Bundle bundle, Application application) {
+ logger.debug("Add - servlet context[%s] - application[%s]", getContext(), key);
+ applications.put(key, application);
+ resourceConfig.add(application);
+ bundles.put(key, bundle);
+ updateWadlSupport();
+ }
+
+ private void updateWadlSupport() {
+ Map<String, Object> properties = resourceConfig.getProperties();
+ if (wadl.hasExtendedWadl()) {
+ properties.put(ResourceConfig.PROPERTY_WADL_GENERATOR_CONFIG, wadl);
+ } else {
+ properties.remove(ResourceConfig.PROPERTY_WADL_GENERATOR_CONFIG);
+ }
+ }
+
+ public void removeApplication(String key) {
+ logger.debug("Remove - servlet context[%s] - application[%s]", getContext(), key);
+ Application remove = applications.remove(key);
+ if (remove != null) {
+ removeResources(resourceConfig.getClasses(), remove.getClasses());
+ removeResources(resourceConfig.getSingletons(), remove.getSingletons());
+ }
+ Bundle bundle = bundles.remove(key);
+ if (bundle != null) {
+ updateWadlSupport();
+ }
+ }
+
+ public void cleanUp() {
+ for (String key : applications.keySet()) {
+ removeApplication(key);
+ }
+ }
+
+ private void removeResources(Set<?> set, Set<?> toRemove) {
+ set.removeAll(toRemove);
+ }
+
+ public boolean isEmpty() {
+ return applications.isEmpty();
+ }
+
+ public void destroy() {
+ getContainer().destroy();
+ }
+
+ public void reload() {
+ getContainer().reload();
+ }
+
+ public ServletContainer getContainer() {
+ return container;
+ }
+
+ public HttpContext getHttpContext() {
+ return context;
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServletManager.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServletManager.java
new file mode 100644
index 00000000000..4a961dce797
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServletManager.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.ws.rs.core.Application;
+import org.eclipse.osee.authorization.admin.AuthorizationAdmin;
+import org.eclipse.osee.executor.admin.CancellableCallable;
+import org.eclipse.osee.executor.admin.ExecutorAdmin;
+import org.eclipse.osee.jaxrs.server.internal.filters.SecurityContextFilter;
+import org.eclipse.osee.jaxrs.server.internal.filters.SecurityContextProviderImpl;
+import org.eclipse.osee.logger.Log;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpService;
+
+/**
+ * @author Roberto E. Escobar
+ */
+public class RestServletManager {
+
+ private static final ApplicationEntry END_OF_QUEUE = new ApplicationEntry(Op.END_OF_QUEUE, null);
+
+ private final LinkedBlockingQueue<ApplicationEntry> pending = new LinkedBlockingQueue<ApplicationEntry>();
+
+ private HttpService httpService;
+ private Log logger;
+ private ExecutorAdmin executorAdmin;
+ private AuthorizationAdmin authorizationAdmin;
+
+ private final AtomicReference<RestServletRegistry> registryRef = new AtomicReference<RestServletRegistry>();
+ private final AtomicReference<Future<?>> futureRef = new AtomicReference<Future<?>>();
+
+ public void setHttpService(HttpService httpService) {
+ this.httpService = httpService;
+ }
+
+ public void setLogger(Log logger) {
+ this.logger = logger;
+ }
+
+ public void setExecutorAdmin(ExecutorAdmin executorAdmin) {
+ this.executorAdmin = executorAdmin;
+ }
+
+ public void setAuthorizationAdmin(AuthorizationAdmin authorizationAdmin) {
+ this.authorizationAdmin = authorizationAdmin;
+ }
+
+ public void start() throws Exception {
+ SecurityContextProvider contextProvider = new SecurityContextProviderImpl(logger, authorizationAdmin);
+ SecurityContextFilter securityFilter = new SecurityContextFilter(contextProvider);
+
+ RestComponentFactory factory = new RestComponentFactory(logger, securityFilter);
+ RestServletRegistry newRegistry = new RestServletRegistry(logger, httpService, factory);
+ RestServletRegistry registry = registryRef.getAndSet(newRegistry);
+ if (registry != null) {
+ registry.cleanUp();
+ }
+
+ CancellableCallable<Void> callable = newRegistrationHelper();
+ Future<?> newFuture = executorAdmin.schedule(callable);
+ Future<?> future = futureRef.getAndSet(newFuture);
+ stopWorker(future);
+ }
+
+ public void stop() {
+ pending.offer(END_OF_QUEUE);
+ Future<?> future = futureRef.getAndSet(null);
+ stopWorker(future);
+
+ RestServletRegistry registry = registryRef.getAndSet(null);
+ if (registry != null) {
+ registry.cleanUp();
+ }
+ }
+
+ private void stopWorker(Future<?> future) {
+ if (future != null) {
+ try {
+ future.get(3, TimeUnit.SECONDS);
+ } catch (Exception ex) {
+ logger.warn(ex, "Error waiting for registration worker to complete");
+ future.cancel(true);
+ }
+ }
+ }
+
+ public void addApplication(ServiceReference<Application> reference) {
+ pending.offer(new ApplicationEntry(Op.ADD, reference));
+ }
+
+ public void removeApplication(ServiceReference<Application> reference) {
+ pending.offer(new ApplicationEntry(Op.REMOVE, reference));
+ }
+
+ private CancellableCallable<Void> newRegistrationHelper() {
+ return new CancellableCallable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ logger.debug("Start - REST Application Registration Helper");
+ boolean isEndOfQueue = false;
+ while (!isEndOfQueue) {
+ Set<ApplicationEntry> toProcess = new HashSet<ApplicationEntry>();
+ ApplicationEntry entry = pending.take();
+ pending.drainTo(toProcess);
+ toProcess.add(entry);
+
+ for (ApplicationEntry item : toProcess) {
+ checkForCancelled();
+
+ RestServletRegistry registry = registryRef.get();
+ if (registry != null) {
+ ServiceReference<Application> reference = item.getReference();
+ switch (item.getOp()) {
+ case ADD:
+ registry.register(reference);
+ break;
+ case REMOVE:
+ registry.deregister(reference);
+ break;
+ default:
+ isEndOfQueue = true;
+ break;
+ }
+ } else {
+ logger.debug("Registry was null while worker was processing [reg/de-reg]-istrations");
+ isEndOfQueue = true;
+ }
+ }
+ }
+ logger.debug("Stop - REST Application Registration Helper");
+ return null;
+ }
+ };
+ }
+
+ private static enum Op {
+ ADD,
+ REMOVE,
+ END_OF_QUEUE;
+ }
+
+ private static final class ApplicationEntry {
+ private final Op op;
+ private final ServiceReference<Application> reference;
+
+ public ApplicationEntry(Op op, ServiceReference<Application> reference) {
+ super();
+ this.op = op;
+ this.reference = reference;
+ }
+
+ public Op getOp() {
+ return op;
+ }
+
+ public ServiceReference<Application> getReference() {
+ return reference;
+ }
+
+ }
+}
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServletRegistry.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServletRegistry.java
new file mode 100644
index 00000000000..d4e24da8eb7
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/RestServletRegistry.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal;
+
+import java.util.Iterator;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.FutureTask;
+import javax.ws.rs.core.Application;
+import org.eclipse.osee.framework.jdk.core.type.LazyObject;
+import org.eclipse.osee.logger.Log;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.HttpService;
+import com.sun.jersey.spi.container.servlet.ServletContainer;
+
+/**
+ * @author Roberto E. Escobar
+ */
+public class RestServletRegistry {
+
+ private final ConcurrentHashMap<String, LazyObject<RestServletContainer>> servlets =
+ new ConcurrentHashMap<String, LazyObject<RestServletContainer>>();
+
+ private final Log logger;
+ private final HttpService httpService;
+ private final RestComponentFactory factory;
+
+ public RestServletRegistry(Log logger, HttpService httpService, RestComponentFactory factory) {
+ super();
+ this.logger = logger;
+ this.httpService = httpService;
+ this.factory = factory;
+ }
+
+ public void register(ServiceReference<Application> reference) throws Exception {
+ String componentName = RestServiceUtils.getComponentName(reference);
+ String contextName = RestServiceUtils.getContextName(reference);
+
+ LazyObject<RestServletContainer> provider = getProvider(contextName);
+ RestServletContainer container = provider.get();
+
+ Bundle bundle = reference.getBundle();
+ Application application = bundle.getBundleContext().getService(reference);
+ container.addApplication(componentName, bundle, application);
+
+ container.reload();
+ }
+
+ public void deregister(ServiceReference<Application> reference) {
+ String componentName = RestServiceUtils.getComponentName(reference);
+ String contextName = RestServiceUtils.getContextName(reference);
+
+ LazyObject<RestServletContainer> provider = getProvider(contextName);
+ RestServletContainer container = provider.get();
+
+ container.removeApplication(componentName);
+ if (container.isEmpty()) {
+ removeContainer(provider);
+ } else {
+ container.reload();
+ }
+ }
+
+ public void cleanUp() {
+ Iterator<LazyObject<RestServletContainer>> iterator = servlets.values().iterator();
+ while (iterator.hasNext()) {
+ LazyObject<RestServletContainer> provider = iterator.next();
+ RestServletContainer container = provider.get();
+ container.cleanUp();
+ removeContainer(provider);
+ iterator.remove();
+ }
+ servlets.clear();
+ }
+
+ private void removeContainer(LazyObject<RestServletContainer> provider) {
+ RestServletContainer container = provider.get();
+ String contextName = container.getContext();
+
+ logger.debug("Remove - servlet context[%s]", contextName);
+ servlets.remove(contextName);
+ httpService.unregister(contextName);
+ container.destroy();
+ provider.invalidate();
+ }
+
+ private LazyObject<RestServletContainer> getProvider(final String contextName) {
+ LazyObject<RestServletContainer> provider = servlets.get(contextName);
+ if (provider == null) {
+ LazyObject<RestServletContainer> newProvider = new ServletContainerProvider(contextName);
+ provider = servlets.putIfAbsent(contextName, newProvider);
+ if (provider == null) {
+ provider = newProvider;
+ }
+ }
+ return provider;
+ }
+
+ private class ServletContainerProvider extends LazyObject<RestServletContainer> implements ObjectProvider<RestServletContainer> {
+
+ private final String contextName;
+
+ public ServletContainerProvider(String contextName) {
+ super();
+ this.contextName = contextName;
+ }
+
+ @Override
+ protected FutureTask<RestServletContainer> createLoaderTask() {
+ Callable<RestServletContainer> newCallable = new Callable<RestServletContainer>() {
+ @Override
+ public RestServletContainer call() throws Exception {
+ logger.debug("Add - servlet context[%s]", contextName);
+ RestServletContainer container = factory.createContainer(contextName);
+
+ String name = container.getContext();
+ ServletContainer servletContainer = container.getContainer();
+ HttpContext httpContext = container.getHttpContext();
+
+ httpService.registerServlet(name, servletContainer, null, httpContext);
+ return container;
+ }
+ };
+ return new FutureTask<RestServletContainer>(newCallable);
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/SecurityContextProvider.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/SecurityContextProvider.java
new file mode 100644
index 00000000000..927e9c04a5f
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/SecurityContextProvider.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal;
+
+import javax.ws.rs.core.SecurityContext;
+import com.sun.jersey.api.core.HttpRequestContext;
+
+/**
+ * @author Roberto E. Escobar
+ */
+public interface SecurityContextProvider {
+
+ SecurityContext getSecurityContext(HttpRequestContext requestContext);
+
+}
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/filters/SecureResourceFilterFactory.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/filters/SecureResourceFilterFactory.java
new file mode 100644
index 00000000000..3aafaa82778
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/filters/SecureResourceFilterFactory.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal.filters;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.osee.jaxrs.NoSecurityFilter;
+import org.eclipse.osee.logger.Log;
+import com.sun.jersey.api.container.filter.servlet.RolesAllowedResourceFilterFactory;
+import com.sun.jersey.api.model.AbstractMethod;
+import com.sun.jersey.spi.container.ResourceFilter;
+
+/**
+ * Ensures the security context filter {@link SecurityContextFilter} is always the first filter in the chain.
+ *
+ * @author Roberto E. Escobar
+ */
+public class SecureResourceFilterFactory extends RolesAllowedResourceFilterFactory {
+
+ private static final String SECURE = "SECURE";
+ private static final String INSECURE = "SKIPPED";
+
+ private final Log logger;
+ private final SecurityContextFilter securityContextFilter;
+
+ public SecureResourceFilterFactory(Log logger, SecurityContextFilter securityContextFilter) {
+ super();
+ this.logger = logger;
+ this.securityContextFilter = securityContextFilter;
+ }
+
+ @Override
+ public List<ResourceFilter> create(AbstractMethod am) {
+ List<ResourceFilter> securityFilters = super.create(am);
+ if (securityFilters == null) {
+ securityFilters = new ArrayList<ResourceFilter>();
+ } else {
+ securityFilters = new ArrayList<ResourceFilter>(securityFilters);
+ }
+
+ boolean secure = isSecured(am);
+ if (secure) {
+ securityFilters.add(0, securityContextFilter);
+ }
+ logger.info("REST Security Filter: [%s] [%s]", secure ? SECURE : INSECURE, am);
+ return securityFilters;
+ }
+
+ private boolean isSecured(AbstractMethod am) {
+ return !am.isAnnotationPresent(NoSecurityFilter.class) && //
+ !am.getResource().isAnnotationPresent(NoSecurityFilter.class);
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/filters/SecurityContextFilter.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/filters/SecurityContextFilter.java
new file mode 100644
index 00000000000..a50be71487f
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/filters/SecurityContextFilter.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal.filters;
+
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.ext.Provider;
+import org.eclipse.osee.jaxrs.server.internal.SecurityContextProvider;
+import com.sun.jersey.spi.container.ContainerRequest;
+import com.sun.jersey.spi.container.ContainerRequestFilter;
+import com.sun.jersey.spi.container.ContainerResponseFilter;
+import com.sun.jersey.spi.container.ResourceFilter;
+
+/**
+ * @author Roberto E. Escobar
+ */
+@Provider
+public class SecurityContextFilter implements ResourceFilter, ContainerRequestFilter {
+
+ private final SecurityContextProvider contextProvider;
+
+ public SecurityContextFilter(SecurityContextProvider contextProvider) {
+ super();
+ this.contextProvider = contextProvider;
+ }
+
+ @Override
+ public ContainerRequest filter(ContainerRequest request) {
+ SecurityContext securityContext = contextProvider.getSecurityContext(request);
+ if (securityContext != null) {
+ request.setSecurityContext(securityContext);
+ }
+ return request;
+ }
+
+ @Override
+ public ContainerRequestFilter getRequestFilter() {
+ return this;
+ }
+
+ @Override
+ public ContainerResponseFilter getResponseFilter() {
+ return null;
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/filters/SecurityContextProviderImpl.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/filters/SecurityContextProviderImpl.java
new file mode 100644
index 00000000000..7d2d677527b
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/filters/SecurityContextProviderImpl.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal.filters;
+
+import java.security.Principal;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.SecurityContext;
+import org.eclipse.osee.authorization.admin.Authorization;
+import org.eclipse.osee.authorization.admin.AuthorizationAdmin;
+import org.eclipse.osee.authorization.admin.AuthorizationRequest;
+import org.eclipse.osee.authorization.admin.AuthorizationRequestBuilder;
+import org.eclipse.osee.framework.jdk.core.util.Strings;
+import org.eclipse.osee.jaxrs.OseeWebApplicationException;
+import org.eclipse.osee.jaxrs.server.internal.SecurityContextProvider;
+import org.eclipse.osee.logger.Log;
+import com.sun.jersey.api.core.HttpRequestContext;
+
+/**
+ * @author Roberto E. Escobar
+ */
+public class SecurityContextProviderImpl implements SecurityContextProvider {
+
+ protected static final String HTTP_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
+ protected static final String AUTHORIZATION_HEADER = "Authorization";
+ protected static final String DATE_HEADER = "Date";
+
+ private final Log logger;
+ private final AuthorizationAdmin authorizationAdmin;
+
+ public SecurityContextProviderImpl(Log logger, AuthorizationAdmin authorizationAdmin) {
+ super();
+ this.logger = logger;
+ this.authorizationAdmin = authorizationAdmin;
+ }
+
+ @Override
+ public SecurityContext getSecurityContext(HttpRequestContext request) {
+ boolean isSecure = request.isSecure();
+ Date requestDate = asDate(request.getHeaderValue(DATE_HEADER));
+ String authType = request.getHeaderValue(AUTHORIZATION_HEADER);
+ String path = request.getPath();
+ String method = request.getMethod();
+
+ AuthorizationRequest authRequest = AuthorizationRequestBuilder.newBuilder()//
+ .secure(isSecure)//
+ .date(requestDate) //
+ .authorizationType(authType) //
+ .method(method) //
+ .path(path) //
+ .build();
+
+ Authorization authorized = authorizationAdmin.authorize(authRequest);
+ return new SecurityContextImpl(authorized);
+ }
+
+ private Date asDate(String value) {
+ Date toReturn = null;
+ if (Strings.isValid(value)) {
+ SimpleDateFormat format = new SimpleDateFormat(HTTP_DATE_FORMAT);
+ try {
+ toReturn = format.parse(value);
+ } catch (ParseException ex) {
+ logger.warn(ex, "Error parsing http request date [%s]", value);
+ }
+ }
+
+ if (toReturn == null) {
+ toReturn = new Date();
+ }
+ return toReturn;
+ }
+
+ private static final class SecurityContextImpl implements SecurityContext {
+
+ private final Authorization authorization;
+
+ public SecurityContextImpl(Authorization authorized) {
+ super();
+ this.authorization = authorized;
+ }
+
+ @Override
+ public Principal getUserPrincipal() {
+ if (authorization == null) {
+ throw new InvalidAuthorizationHeaderException();
+ }
+ return authorization.getPrincipal();
+ }
+
+ @Override
+ public boolean isUserInRole(String role) {
+ if (authorization == null) {
+ throw new InvalidAuthorizationHeaderException();
+ }
+ return authorization.isInRole(role);
+ }
+
+ @Override
+ public boolean isSecure() {
+ if (authorization == null) {
+ throw new InvalidAuthorizationHeaderException();
+ }
+ return authorization.isSecure();
+ }
+
+ @Override
+ public String getAuthenticationScheme() {
+ if (authorization == null) {
+ throw new InvalidAuthorizationHeaderException();
+ }
+ return authorization.getScheme();
+ }
+ }
+
+ private static final class InvalidAuthorizationHeaderException extends OseeWebApplicationException {
+
+ private static final long serialVersionUID = -7930846912940821509L;
+
+ public static final String ERROR_MESSAGE =
+ "Authorization Error - This could be due to missing properties in the header.";
+
+ public InvalidAuthorizationHeaderException() {
+ super(Status.UNAUTHORIZED, ERROR_MESSAGE);
+ }
+
+ }
+}
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/resources/ApplicationsResource.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/resources/ApplicationsResource.java
new file mode 100644
index 00000000000..5cd18ceef84
--- /dev/null
+++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/resources/ApplicationsResource.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Boeing.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.jaxrs.server.internal.resources;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.List;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import org.eclipse.osee.jaxrs.ApplicationInfo;
+import org.eclipse.osee.jaxrs.server.internal.ObjectProvider;
+import org.eclipse.osee.jaxrs.server.internal.RestServiceUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * @author Roberto E. Escobar
+ */
+@Path("application-details")
+public class ApplicationsResource {
+
+ private final ObjectProvider<Iterable<Bundle>> provider;
+
+ public ApplicationsResource(ObjectProvider<Iterable<Bundle>> provider) {
+ super();
+ this.provider = provider;
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ public List<ApplicationInfo> getApplicationsInfo() {
+ List<ApplicationInfo> toReturn = new ArrayList<ApplicationInfo>();
+ Iterable<Bundle> bundles = provider.get();
+ for (Bundle bundle : bundles) {
+ Dictionary<String, String> headers = bundle.getHeaders();
+
+ String bundleName = headers.get(Constants.BUNDLE_SYMBOLICNAME);
+ String bundleVersion = headers.get(Constants.BUNDLE_VERSION);
+
+ ServiceReference<?>[] references = bundle.getRegisteredServices();
+ for (ServiceReference<?> reference : references) {
+ String[] object = (String[]) reference.getProperty("objectClass");
+ String clazzType = Arrays.deepToString(object);
+ if (clazzType.contains(Application.class.getSimpleName())) {
+ String componentName = RestServiceUtils.getComponentName(reference);
+ String contextName = RestServiceUtils.getContextName(reference);
+
+ ApplicationInfo info = new ApplicationInfo();
+ info.setBundleName(bundleName);
+ info.setVersion(bundleVersion);
+ info.setApplicationName(componentName);
+ info.setUri(contextName);
+ toReturn.add(info);
+ }
+
+ }
+ }
+ return toReturn;
+ }
+}

Back to the top