You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jl...@apache.org on 2018/04/26 15:13:36 UTC
[1/8] tomee git commit: Implement mp-jwt (first shoot)
Repository: tomee
Updated Branches:
refs/heads/fb_tomee8 f3c5c2d6e -> 6d591bbbd
Implement mp-jwt (first shoot)
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/82670f9b
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/82670f9b
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/82670f9b
Branch: refs/heads/fb_tomee8
Commit: 82670f9b43a63ed28ac23ea9ec57846bcb8884e9
Parents: 58a3fa7
Author: Jean-Louis Monteiro <je...@gmail.com>
Authored: Tue Apr 17 22:31:11 2018 +0200
Committer: Jean-Louis Monteiro <je...@gmail.com>
Committed: Tue Apr 17 22:31:11 2018 +0200
----------------------------------------------------------------------
.../core/security/AbstractSecurityService.java | 12 ++++--
pom.xml | 1 +
.../rs/event/ExtensionProviderRegistration.java | 4 +-
.../tomee/microprofile/jwt/TCKTokenParser.java | 40 ++++++++++++++++++++
...lipse.microprofile.jwt.tck.util.ITokenParser | 1 +
tck/microprofile-tck/pom.xml | 1 +
.../tomee/catalina/TomcatSecurityService.java | 21 ++++++++++
tomee/tomee-microprofile-webapp/pom.xml | 16 ++++++++
8 files changed, 91 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/82670f9b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
index 57e2c9c..233db15 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
@@ -151,15 +151,17 @@ public abstract class AbstractSecurityService implements DestroyableResource, Se
final String moduleID = newContext.getBeanContext().getModuleID();
JavaSecurityManagers.setContextID(moduleID);
+ final SecurityContext defaultSecurityContext = getDefaultSecurityContext();
+
final ProvidedSecurityContext providedSecurityContext = newContext.get(ProvidedSecurityContext.class);
SecurityContext securityContext = oldContext != null ? oldContext.get(SecurityContext.class) :
- (providedSecurityContext != null ? providedSecurityContext.context : null);
- if (providedSecurityContext == null && (securityContext == null || securityContext == defaultContext)) {
+ (providedSecurityContext != null ? providedSecurityContext.context : null);
+ if (providedSecurityContext == null && (securityContext == null || securityContext == defaultSecurityContext)) {
final Identity identity = clientIdentity.get();
if (identity != null) {
securityContext = new SecurityContext(identity.subject);
} else {
- securityContext = defaultContext;
+ securityContext = defaultSecurityContext;
}
}
@@ -398,6 +400,10 @@ public abstract class AbstractSecurityService implements DestroyableResource, Se
}
}
+ protected SecurityContext getDefaultSecurityContext() {
+ return defaultContext;
+ }
+
public static final class ProvidedSecurityContext {
public final SecurityContext context;
http://git-wip-us.apache.org/repos/asf/tomee/blob/82670f9b/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 53ded49..82b50dd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -506,6 +506,7 @@
<module>gradle</module>
<module>container</module>
<module>server</module>
+ <module>mp-jwt</module>
<module>examples</module>
<module>assembly</module>
<module>tck</module>
http://git-wip-us.apache.org/repos/asf/tomee/blob/82670f9b/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/event/ExtensionProviderRegistration.java
----------------------------------------------------------------------
diff --git a/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/event/ExtensionProviderRegistration.java b/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/event/ExtensionProviderRegistration.java
index cfae25c..932a6bf 100644
--- a/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/event/ExtensionProviderRegistration.java
+++ b/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/event/ExtensionProviderRegistration.java
@@ -28,9 +28,9 @@ public class ExtensionProviderRegistration {
private final List<Object> providers;
private final AppContext appContext;
- public ExtensionProviderRegistration(final AppContext ctx, final List<Object> existings) {
+ public ExtensionProviderRegistration(final AppContext ctx, final List<Object> providers) {
this.appContext = ctx;
- this.providers = existings;
+ this.providers = providers;
}
public AppContext getAppContext() {
http://git-wip-us.apache.org/repos/asf/tomee/blob/82670f9b/tck/microprofile-tck/jwt/src/main/java/org/apache/tomee/microprofile/jwt/TCKTokenParser.java
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/src/main/java/org/apache/tomee/microprofile/jwt/TCKTokenParser.java b/tck/microprofile-tck/jwt/src/main/java/org/apache/tomee/microprofile/jwt/TCKTokenParser.java
new file mode 100644
index 0000000..ae563ec
--- /dev/null
+++ b/tck/microprofile-tck/jwt/src/main/java/org/apache/tomee/microprofile/jwt/TCKTokenParser.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt;
+
+import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo;
+import org.apache.tomee.microprofile.jwt.principal.DefaultJWTCallerPrincipalFactory;
+import org.apache.tomee.microprofile.jwt.principal.JWTCallerPrincipalFactory;
+import org.eclipse.microprofile.jwt.JsonWebToken;
+import org.eclipse.microprofile.jwt.tck.util.ITokenParser;
+
+import java.security.PublicKey;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * MP-JWT TCK harness class to parse a token string
+ */
+public class TCKTokenParser implements ITokenParser {
+
+ @Override
+ public JsonWebToken parse(final String bearerToken, final String issuer, final PublicKey publicKey) throws Exception {
+ final JWTAuthContextInfo authContextInfo = new JWTAuthContextInfo((RSAPublicKey) publicKey, issuer);
+ final JWTCallerPrincipalFactory factory = DefaultJWTCallerPrincipalFactory.instance();
+ return factory.parse(bearerToken, authContextInfo);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/82670f9b/tck/microprofile-tck/jwt/src/test/resources/META-INF/services/org.eclipse.microprofile.jwt.tck.util.ITokenParser
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/src/test/resources/META-INF/services/org.eclipse.microprofile.jwt.tck.util.ITokenParser b/tck/microprofile-tck/jwt/src/test/resources/META-INF/services/org.eclipse.microprofile.jwt.tck.util.ITokenParser
new file mode 100644
index 0000000..4dcc059
--- /dev/null
+++ b/tck/microprofile-tck/jwt/src/test/resources/META-INF/services/org.eclipse.microprofile.jwt.tck.util.ITokenParser
@@ -0,0 +1 @@
+org.apache.tomee.microprofile.jwt.TCKTokenParser
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/82670f9b/tck/microprofile-tck/pom.xml
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/pom.xml b/tck/microprofile-tck/pom.xml
index c48b7c5..9726358 100644
--- a/tck/microprofile-tck/pom.xml
+++ b/tck/microprofile-tck/pom.xml
@@ -32,6 +32,7 @@
<modules>
<module>config</module>
+ <module>jwt</module>
</modules>
</project>
http://git-wip-us.apache.org/repos/asf/tomee/blob/82670f9b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java
----------------------------------------------------------------------
diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java
index 81bffd4..e0e77be 100644
--- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java
+++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java
@@ -39,6 +39,7 @@ import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.Callable;
public class TomcatSecurityService extends AbstractSecurityService {
private static final boolean ONLY_DEFAULT_REALM = "true".equals(SystemInstance.get().getProperty("tomee.realm.only-default", "false"));
@@ -330,4 +331,24 @@ public class TomcatSecurityService extends AbstractSecurityService {
}
}
+ @Override
+ protected SecurityContext getDefaultSecurityContext() {
+ final Request request = OpenEJBSecurityListener.requests.get();
+ if (request != null) {
+ final Object subjectCallable = request.getAttribute("javax.security.auth.subject.callable");
+ if (subjectCallable != null && Callable.class.isInstance(subjectCallable)) {
+ // maybe we should check, but it's so specific ...
+ try {
+ final Subject subject = (Subject) Callable.class.cast(subjectCallable).call();
+ return new SecurityContext(subject);
+
+ } catch (final Exception e) {
+ // ignore and let it go to the default implementation
+ }
+ }
+ }
+
+ return super.getDefaultSecurityContext();
+ }
+
}
http://git-wip-us.apache.org/repos/asf/tomee/blob/82670f9b/tomee/tomee-microprofile-webapp/pom.xml
----------------------------------------------------------------------
diff --git a/tomee/tomee-microprofile-webapp/pom.xml b/tomee/tomee-microprofile-webapp/pom.xml
index 927bafe..c5f56ce 100644
--- a/tomee/tomee-microprofile-webapp/pom.xml
+++ b/tomee/tomee-microprofile-webapp/pom.xml
@@ -39,6 +39,9 @@
<microprofile.config.api.version>1.3-SNAPSHOT</microprofile.config.api.version>
<microprofile.config.impl.version>1.2-SNAPSHOT</microprofile.config.impl.version>
+
+ <microprofile.jwt.api.version>1.1-SNAPSHOT</microprofile.jwt.api.version>
+ <microprofile.jwt.impl.version>${project.version}</microprofile.jwt.impl.version>
</properties>
<dependencies>
@@ -60,6 +63,19 @@
<artifactId>geronimo-config-impl</artifactId>
<version>${microprofile.config.impl.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.eclipse.microprofile.jwt</groupId>
+ <artifactId>microprofile-jwt-auth-api</artifactId>
+ <version>${microprofile.jwt.api.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mp-jwt</artifactId>
+ <version>${microprofile.jwt.impl.version}</version>
+ </dependency>
+
</dependencies>
<build>
[4/8] tomee git commit: Make a simple test case to wire up everything
and start adding a simple UI on top
Posted by jl...@apache.org.
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/view/container.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/container.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/container.js
new file mode 100644
index 0000000..73a57f1
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/view/container.js
@@ -0,0 +1,62 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ var deps = ['app/js/templates', 'app/js/i18n', 'lib/backbone'];
+ define(deps, function (templates) {
+
+ var View = Backbone.View.extend({
+ el: 'body',
+
+ showView: function (view) {
+ var me = this;
+ var contentarea = me.$('.ux-contentarea');
+ if (me.currentView) {
+ me.currentView.$el.detach();
+ }
+ me.currentView = view;
+ me.currentView.render();
+ contentarea.append(me.currentView.el);
+ if (view.renderCallback) {
+ view.renderCallback();
+ }
+ me.$('.ux-app-menu-item').removeClass('active');
+ var myMenuItem = me.$('li.ux-app-menu-item.' + view.className);
+ myMenuItem.addClass('active');
+ },
+
+ render: function () {
+ if (this.options.isRendered) {
+ return this;
+ }
+ var html = templates.getValue('container', {
+ userName: ''
+ });
+ this.$el.html(html);
+
+ // render it only once
+ this.options.isRendered = true;
+ return this;
+ }
+ });
+
+ return new View({});
+ });
+}());
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/view/movie.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/movie.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/movie.js
new file mode 100644
index 0000000..0417945
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/view/movie.js
@@ -0,0 +1,75 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ var deps = ['app/js/templates', 'lib/underscore', 'lib/backbone', 'app/js/id'];
+ define(deps, function (templates, underscore) {
+
+ var View = Backbone.View.extend({
+ tagName: 'div',
+ className: 'modal ux-movie-window',
+ events: {
+ 'click .ux-application': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ me.trigger('show-application', {});
+ },
+ 'click .ux-close': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ me.remove();
+ },
+ 'click .ux-save': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ var model = me.model;
+
+ function set(name) {
+ var field = $(me.$el.find('.ux-' + name).get(0));
+ model.set(name, field.val());
+ }
+
+ set('title');
+ set('director');
+ set('genre');
+ set('rating');
+ set('year');
+ me.trigger('save-model', {
+ model: model
+ });
+ }
+ },
+ render: function () {
+ var me = this;
+ me.$el.empty();
+ me.$el.append(templates.getValue('movie', {
+ title: me.model.get('title'),
+ director: me.model.get('director'),
+ genre: me.model.get('genre'),
+ rating: me.model.get('rating'),
+ year: me.model.get('year'),
+ currentYear: new Date().getFullYear()
+ }));
+ return me;
+ }
+ });
+ return View;
+ });
+}());
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/index.jsp
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/index.jsp b/examples/rest-mp-jwt/src/main/webapp/index.jsp
new file mode 100644
index 0000000..63d3e42
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/index.jsp
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Moviefun</title>
+ <link href="<c:url value='/webjars/bootstrap/3.1.0/css/bootstrap.min.css'/>" rel="stylesheet">
+ <link href="<c:url value='/app/app.less'/>" rel="stylesheet/less" type="text/css">
+ <script src="<c:url value='/webjars/requirejs/2.1.10/require.min.js'/>"></script>
+ <script type="text/javascript">
+ window.ux = window.ux || {};
+ window.ux.SESSION_ID = "<%=request.getSession().getId()%>";
+ window.ux.ROOT_URL = "<c:url value='/'/>".replace(';jsessionid=' + window.ux.SESSION_ID, '');
+ </script>
+ <script src="<c:url value='/app/config.js'/>"></script>
+ <script src="<c:url value='/app/js/start.js'/>"></script>
+</head>
+<body></body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/MoviesTest.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/MoviesTest.java b/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/MoviesTest.java
new file mode 100644
index 0000000..b18e64e
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/MoviesTest.java
@@ -0,0 +1,88 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.moviefun;
+
+import org.apache.cxf.feature.LoggingFeature;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.johnzon.jaxrs.JohnzonProvider;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.superbiz.moviefun.rest.ApplicationConfig;
+import org.superbiz.moviefun.rest.LoadRest;
+import org.superbiz.moviefun.rest.MoviesMPJWTConfigurationProvider;
+import org.superbiz.moviefun.rest.MoviesRest;
+import org.superbiz.rest.GreetingService;
+
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashMap;
+
+import static java.util.Collections.singletonList;
+
+@RunWith(Arquillian.class)
+public class MoviesTest {
+
+ @Deployment(testable = false)
+ public static WebArchive createDeployment() {
+ final WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "test.war")
+ .addClasses(Movie.class, MoviesBean.class, MoviesTest.class, LoadRest.class)
+ .addClasses(MoviesRest.class, GreetingService.class, ApplicationConfig.class)
+ .addClass(MoviesMPJWTConfigurationProvider.class)
+ .addAsWebInfResource(new StringAsset("<beans/>"), "beans.xml")
+ .addAsResource(new ClassLoaderAsset("META-INF/persistence.xml"), "META-INF/persistence.xml");
+
+ System.out.println(webArchive.toString(true));
+
+ return webArchive;
+ }
+
+ @ArquillianResource
+ private URL base;
+
+ @Test
+ public void sthg() throws Exception {
+
+ final WebClient webClient = WebClient
+ .create(base.toExternalForm(), singletonList(new JohnzonProvider<>()), singletonList(new LoggingFeature()), null);
+
+ webClient
+ .reset()
+ .path("/rest/greeting/")
+ .get(String.class);
+
+ final Collection<? extends Movie> movies = webClient
+ .reset()
+ .path("/rest/movies/")
+ .header("Authorization", "Bearer " + token())
+ .getCollection(Movie.class);
+
+ System.out.println(movies);
+ }
+
+ private String token() throws Exception {
+ HashMap<String, Long> timeClaims = new HashMap<>();
+ return TokenUtils.generateTokenString("/Token1.json", null, timeClaims);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/TokenUtils.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/TokenUtils.java b/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/TokenUtils.java
new file mode 100644
index 0000000..5aa34b4
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/TokenUtils.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2016-2017 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.superbiz.moviefun;
+
+import com.nimbusds.jose.JOSEObjectType;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.JWSHeader;
+import com.nimbusds.jose.JWSSigner;
+import com.nimbusds.jose.crypto.MACSigner;
+import com.nimbusds.jose.crypto.RSASSASigner;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.SignedJWT;
+import net.minidev.json.JSONObject;
+import net.minidev.json.parser.JSONParser;
+import org.eclipse.microprofile.jwt.Claims;
+
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import static net.minidev.json.parser.JSONParser.DEFAULT_PERMISSIVE_MODE;
+
+/**
+ * Utilities for generating a JWT for testing
+ */
+public class TokenUtils {
+ private TokenUtils() {
+ }
+
+ /**
+ * Utility method to generate a JWT string from a JSON resource file that is signed by the privateKey.pem
+ * test resource key.
+ *
+ * @param jsonResName - name of test resources file
+ * @return the JWT string
+ * @throws Exception on parse failure
+ */
+ public static String generateTokenString(String jsonResName) throws Exception {
+ return generateTokenString(jsonResName, Collections.emptySet());
+ }
+
+ /**
+ * Utility method to generate a JWT string from a JSON resource file that is signed by the privateKey.pem
+ * test resource key, possibly with invalid fields.
+ *
+ * @param jsonResName - name of test resources file
+ * @param invalidClaims - the set of claims that should be added with invalid values to test failure modes
+ * @return the JWT string
+ * @throws Exception on parse failure
+ */
+ public static String generateTokenString(String jsonResName, Set<InvalidClaims> invalidClaims) throws Exception {
+ return generateTokenString(jsonResName, invalidClaims, null);
+ }
+
+ /**
+ * Utility method to generate a JWT string from a JSON resource file that is signed by the privateKey.pem
+ * test resource key, possibly with invalid fields.
+ *
+ * @param jsonResName - name of test resources file
+ * @param invalidClaims - the set of claims that should be added with invalid values to test failure modes
+ * @param timeClaims - used to return the exp, iat, auth_time claims
+ * @return the JWT string
+ * @throws Exception on parse failure
+ */
+ public static String generateTokenString(String jsonResName, Set<InvalidClaims> invalidClaims, Map<String, Long> timeClaims) throws Exception {
+ if (invalidClaims == null) {
+ invalidClaims = Collections.emptySet();
+ }
+ InputStream contentIS = TokenUtils.class.getResourceAsStream(jsonResName);
+ byte[] tmp = new byte[4096];
+ int length = contentIS.read(tmp);
+ byte[] content = new byte[length];
+ System.arraycopy(tmp, 0, content, 0, length);
+
+ JSONParser parser = new JSONParser(DEFAULT_PERMISSIVE_MODE);
+ JSONObject jwtContent = (JSONObject) parser.parse(content);
+ // Change the issuer to INVALID_ISSUER for failure testing if requested
+ if (invalidClaims.contains(InvalidClaims.ISSUER)) {
+ jwtContent.put(Claims.iss.name(), "INVALID_ISSUER");
+ }
+ long currentTimeInSecs = currentTimeInSecs();
+ long exp = currentTimeInSecs + 300;
+ // Check for an input exp to override the default of now + 300 seconds
+ if (timeClaims != null && timeClaims.containsKey(Claims.exp.name())) {
+ exp = timeClaims.get(Claims.exp.name());
+ }
+ jwtContent.put(Claims.iat.name(), currentTimeInSecs);
+ jwtContent.put(Claims.auth_time.name(), currentTimeInSecs);
+ // If the exp claim is not updated, it will be an old value that should be seen as expired
+ if (!invalidClaims.contains(InvalidClaims.EXP)) {
+ jwtContent.put(Claims.exp.name(), exp);
+ }
+ if (timeClaims != null) {
+ timeClaims.put(Claims.iat.name(), currentTimeInSecs);
+ timeClaims.put(Claims.auth_time.name(), currentTimeInSecs);
+ timeClaims.put(Claims.exp.name(), exp);
+ }
+
+ PrivateKey pk;
+ if (invalidClaims.contains(InvalidClaims.SIGNER)) {
+ // Generate a new random private key to sign with to test invalid signatures
+ KeyPair keyPair = generateKeyPair(2048);
+ pk = keyPair.getPrivate();
+ } else {
+ // Use the test private key associated with the test public key for a valid signature
+ pk = readPrivateKey("/privateKey.pem");
+ }
+
+ // Create RSA-signer with the private key
+ JWSSigner signer = new RSASSASigner(pk);
+ JWTClaimsSet claimsSet = JWTClaimsSet.parse(jwtContent);
+ JWSAlgorithm alg = JWSAlgorithm.RS256;
+ if (invalidClaims.contains(InvalidClaims.ALG)) {
+ alg = JWSAlgorithm.HS256;
+ SecureRandom random = new SecureRandom();
+ BigInteger secret = BigInteger.probablePrime(256, random);
+ signer = new MACSigner(secret.toByteArray());
+ }
+ JWSHeader jwtHeader = new JWSHeader.Builder(alg)
+ .keyID("/privateKey.pem")
+ .type(JOSEObjectType.JWT)
+ .build();
+ SignedJWT signedJWT = new SignedJWT(jwtHeader, claimsSet);
+ signedJWT.sign(signer);
+ return signedJWT.serialize();
+ }
+
+ /**
+ * Read a PEM encoded private key from the classpath
+ *
+ * @param pemResName - key file resource name
+ * @return PrivateKey
+ * @throws Exception on decode failure
+ */
+ public static PrivateKey readPrivateKey(String pemResName) throws Exception {
+ InputStream contentIS = TokenUtils.class.getResourceAsStream(pemResName);
+ byte[] tmp = new byte[4096];
+ int length = contentIS.read(tmp);
+ return decodePrivateKey(new String(tmp, 0, length));
+ }
+
+ /**
+ * Read a PEM encoded public key from the classpath
+ *
+ * @param pemResName - key file resource name
+ * @return PublicKey
+ * @throws Exception on decode failure
+ */
+ public static PublicKey readPublicKey(String pemResName) throws Exception {
+ InputStream contentIS = TokenUtils.class.getResourceAsStream(pemResName);
+ byte[] tmp = new byte[4096];
+ int length = contentIS.read(tmp);
+ return decodePublicKey(new String(tmp, 0, length));
+ }
+
+ /**
+ * Generate a new RSA keypair.
+ *
+ * @param keySize - the size of the key
+ * @return KeyPair
+ * @throws NoSuchAlgorithmException on failure to load RSA key generator
+ */
+ public static KeyPair generateKeyPair(int keySize) throws NoSuchAlgorithmException {
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+ keyPairGenerator.initialize(keySize);
+ return keyPairGenerator.genKeyPair();
+ }
+
+ /**
+ * Decode a PEM encoded private key string to an RSA PrivateKey
+ *
+ * @param pemEncoded - PEM string for private key
+ * @return PrivateKey
+ * @throws Exception on decode failure
+ */
+ public static PrivateKey decodePrivateKey(String pemEncoded) throws Exception {
+ pemEncoded = removeBeginEnd(pemEncoded);
+ byte[] pkcs8EncodedBytes = Base64.getDecoder().decode(pemEncoded);
+
+ // extract the private key
+
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ return kf.generatePrivate(keySpec);
+ }
+
+ /**
+ * Decode a PEM encoded public key string to an RSA PublicKey
+ *
+ * @param pemEncoded - PEM string for private key
+ * @return PublicKey
+ * @throws Exception on decode failure
+ */
+ public static PublicKey decodePublicKey(String pemEncoded) throws Exception {
+ pemEncoded = removeBeginEnd(pemEncoded);
+ byte[] encodedBytes = Base64.getDecoder().decode(pemEncoded);
+
+ X509EncodedKeySpec spec = new X509EncodedKeySpec(encodedBytes);
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ return kf.generatePublic(spec);
+ }
+
+ private static String removeBeginEnd(String pem) {
+ pem = pem.replaceAll("-----BEGIN (.*)-----", "");
+ pem = pem.replaceAll("-----END (.*)----", "");
+ pem = pem.replaceAll("\r\n", "");
+ pem = pem.replaceAll("\n", "");
+ return pem.trim();
+ }
+
+ /**
+ * @return the current time in seconds since epoch
+ */
+ public static int currentTimeInSecs() {
+ long currentTimeMS = System.currentTimeMillis();
+ return (int) (currentTimeMS / 1000);
+ }
+
+ /**
+ * Enums to indicate which claims should be set to invalid values for testing failure modes
+ */
+ public enum InvalidClaims {
+ ISSUER, // Set an invalid issuer
+ EXP, // Set an invalid expiration
+ SIGNER, // Sign the token with the incorrect private key
+ ALG, // Sign the token with the correct private key, but HS
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/java/org/superbiz/rest/GreetingServiceTest.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/java/org/superbiz/rest/GreetingServiceTest.java b/examples/rest-mp-jwt/src/test/java/org/superbiz/rest/GreetingServiceTest.java
new file mode 100644
index 0000000..f38063f
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/java/org/superbiz/rest/GreetingServiceTest.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.rest;
+
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.openejb.jee.WebApp;
+import org.apache.openejb.junit.ApplicationComposer;
+import org.apache.openejb.testing.Classes;
+import org.apache.openejb.testing.EnableServices;
+import org.apache.openejb.testing.Module;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.ws.rs.core.MediaType;
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+
+@EnableServices(value = "jaxrs", httpDebug = true)
+@RunWith(ApplicationComposer.class)
+public class GreetingServiceTest {
+
+ @Module
+ @Classes(GreetingService.class)
+ public WebApp app() {
+ return new WebApp().contextRoot("test");
+ }
+
+ @Test
+ public void get() throws IOException {
+ final String message = WebClient.create("http://localhost:4204")
+ .path("/test/greeting/")
+ .accept(MediaType.APPLICATION_JSON_TYPE)
+ .get(String.class);
+ assertEquals("Hi Microprofile JWT!", message);
+ }
+
+ @Test
+ public void post() throws IOException {
+ final String message = WebClient.create("http://localhost:4204")
+ .path("/test/greeting/")
+ .type(MediaType.APPLICATION_JSON_TYPE)
+ .accept(MediaType.APPLICATION_JSON_TYPE)
+ .post("Hi REST!", String.class);
+ assertEquals("hi rest!", message);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/resources/META-INF/application-client.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/resources/META-INF/application-client.xml b/examples/rest-mp-jwt/src/test/resources/META-INF/application-client.xml
new file mode 100644
index 0000000..1e91dca
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/resources/META-INF/application-client.xml
@@ -0,0 +1 @@
+<application-client/>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/resources/Token1.json
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/resources/Token1.json b/examples/rest-mp-jwt/src/test/resources/Token1.json
new file mode 100644
index 0000000..32b03c8
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/resources/Token1.json
@@ -0,0 +1,20 @@
+{
+ "iss": "https://server.example.com",
+ "jti": "a-123",
+ "sub": "24400320",
+ "upn": "jdoe@example.com",
+ "preferred_username": "jdoe",
+ "aud": "s6BhdRkqt3",
+ "exp": 1311281970,
+ "iat": 1311280970,
+ "auth_time": 1311280969,
+ "roles": [
+ "Echoer"
+ ],
+ "groups": [
+ "Echoer",
+ "Tester",
+ "group1",
+ "group2"
+ ]
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/resources/Token2.json
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/resources/Token2.json b/examples/rest-mp-jwt/src/test/resources/Token2.json
new file mode 100644
index 0000000..d69f61a
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/resources/Token2.json
@@ -0,0 +1,12 @@
+{
+ "iss": "https://server.example.com",
+ "jti": "a-123.2",
+ "sub": "24400320#2",
+ "upn": "jdoe2@example.com",
+ "preferred_username": "jdoe",
+ "aud": "s6BhdRkqt3.2",
+ "exp": 1311281970,
+ "iat": 1311280970,
+ "auth_time": 1311280969,
+ "groups": ["Echoer2", "Tester", "Token2Role", "group1.2", "group2.2"]
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/resources/arquillian.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/resources/arquillian.xml b/examples/rest-mp-jwt/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..4744e7a
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/resources/arquillian.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<arquillian
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ >
+
+ <container qualifier="tomee" default="true">
+ <configuration>
+ <property name="httpPort">-1</property>
+ <property name="stopPort">-1</property>
+ <property name="classifier">microprofile</property>
+ <property name="dir">target/apache-tomee-remote</property>
+ <property name="appWorkingDir">target/arquillian-test-working-dir</property>
+ </configuration>
+ </container>
+</arquillian>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/resources/privateKey.pem
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/resources/privateKey.pem b/examples/rest-mp-jwt/src/test/resources/privateKey.pem
new file mode 100644
index 0000000..e20d80b
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/resources/privateKey.pem
@@ -0,0 +1,28 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCWK8UjyoHgPTLa
+PLQJ8SoXLLjpHSjtLxMqmzHnFscqhTVVaDpCRCb6e3Ii/WniQTWw8RA7vf4djz4H
+OzvlfBFNgvUGZHXDwnmGaNVaNzpHYFMEYBhE8VGGiveSkzqeLZI+Y02G6sQAfDtN
+qqzM/l5QX8X34oQFaTBW1r49nftvCpITiwJvWyhkWtXP9RP8sXi1im5Vi3dhupOh
+nelk5n0BfajUYIbfHA6ORzjHRbt7NtBl0L2J+0/FUdHyKs6KMlFGNw8O0Dq88qnM
+uXoLJiewhg9332W3DFMeOveel+//cvDnRsCRtPgd4sXFPHh+UShkso7+DRsChXa6
+oGGQD3GdAgMBAAECggEAAjfTSZwMHwvIXIDZB+yP+pemg4ryt84iMlbofclQV8hv
+6TsI4UGwcbKxFOM5VSYxbNOisb80qasb929gixsyBjsQ8284bhPJR7r0q8h1C+jY
+URA6S4pk8d/LmFakXwG9Tz6YPo3pJziuh48lzkFTk0xW2Dp4SLwtAptZY/+ZXyJ6
+96QXDrZKSSM99Jh9s7a0ST66WoxSS0UC51ak+Keb0KJ1jz4bIJ2C3r4rYlSu4hHB
+Y73GfkWORtQuyUDa9yDOem0/z0nr6pp+pBSXPLHADsqvZiIhxD/O0Xk5I6/zVHB3
+zuoQqLERk0WvA8FXz2o8AYwcQRY2g30eX9kU4uDQAQKBgQDmf7KGImUGitsEPepF
+KH5yLWYWqghHx6wfV+fdbBxoqn9WlwcQ7JbynIiVx8MX8/1lLCCe8v41ypu/eLtP
+iY1ev2IKdrUStvYRSsFigRkuPHUo1ajsGHQd+ucTDf58mn7kRLW1JGMeGxo/t32B
+m96Af6AiPWPEJuVfgGV0iwg+HQKBgQCmyPzL9M2rhYZn1AozRUguvlpmJHU2DpqS
+34Q+7x2Ghf7MgBUhqE0t3FAOxEC7IYBwHmeYOvFR8ZkVRKNF4gbnF9RtLdz0DMEG
+5qsMnvJUSQbNB1yVjUCnDAtElqiFRlQ/k0LgYkjKDY7LfciZl9uJRl0OSYeX/qG2
+tRW09tOpgQKBgBSGkpM3RN/MRayfBtmZvYjVWh3yjkI2GbHA1jj1g6IebLB9SnfL
+WbXJErCj1U+wvoPf5hfBc7m+jRgD3Eo86YXibQyZfY5pFIh9q7Ll5CQl5hj4zc4Y
+b16sFR+xQ1Q9Pcd+BuBWmSz5JOE/qcF869dthgkGhnfVLt/OQzqZluZRAoGAXQ09
+nT0TkmKIvlza5Af/YbTqEpq8mlBDhTYXPlWCD4+qvMWpBII1rSSBtftgcgca9XLB
+MXmRMbqtQeRtg4u7dishZVh1MeP7vbHsNLppUQT9Ol6lFPsd2xUpJDc6BkFat62d
+Xjr3iWNPC9E9nhPPdCNBv7reX7q81obpeXFMXgECgYEAmk2Qlus3OV0tfoNRqNpe
+Mb0teduf2+h3xaI1XDIzPVtZF35ELY/RkAHlmWRT4PCdR0zXDidE67L6XdJyecSt
+FdOUH8z5qUraVVebRFvJqf/oGsXc4+ex1ZKUTbY0wqY1y9E39yvB3MaTmZFuuqk8
+f3cg+fr8aou7pr9SHhJlZCU=
+-----END RSA PRIVATE KEY-----
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/resources/publicKey.pem
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/resources/publicKey.pem b/examples/rest-mp-jwt/src/test/resources/publicKey.pem
new file mode 100644
index 0000000..a1dc20c
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/resources/publicKey.pem
@@ -0,0 +1,9 @@
+-----BEGIN RSA PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq
+Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR
+TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e
+UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9
+AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn
+sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x
+nQIDAQAB
+-----END RSA PUBLIC KEY-----
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
index 051f05a..ca69b0a 100644
--- a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
@@ -18,7 +18,6 @@ package org.apache.tomee.microprofile.jwt.cdi;
import org.apache.tomee.microprofile.jwt.MPJWTFilter;
import org.apache.tomee.microprofile.jwt.MPJWTInitializer;
-import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfoProvider;
import org.eclipse.microprofile.jwt.Claim;
import javax.enterprise.event.Observes;
@@ -37,24 +36,13 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
-import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class MPJWTCDIExtension implements Extension {
- private static final Predicate<InjectionPoint> NOT_PROVIDERS = new Predicate<InjectionPoint>() {
- @Override
- public boolean test(final InjectionPoint ip) {
- return (Class.class.isInstance(ip.getType())) || (ParameterizedType.class.isInstance(ip.getType()) && ((ParameterizedType) ip.getType()).getRawType() != Provider.class);
- }
- };
- private static final Predicate<InjectionPoint> NOT_INSTANCES = new Predicate<InjectionPoint>() {
- @Override
- public boolean test(final InjectionPoint ip) {
- return (Class.class.isInstance(ip.getType())) || (ParameterizedType.class.isInstance(ip.getType()) && ((ParameterizedType) ip.getType()).getRawType() != Instance.class);
- }
- };
+ private static final Predicate<InjectionPoint> NOT_PROVIDERS = ip -> (Class.class.isInstance(ip.getType())) || (ParameterizedType.class.isInstance(ip.getType()) && ((ParameterizedType) ip.getType()).getRawType() != Provider.class);
+ private static final Predicate<InjectionPoint> NOT_INSTANCES = ip -> (Class.class.isInstance(ip.getType())) || (ParameterizedType.class.isInstance(ip.getType()) && ((ParameterizedType) ip.getType()).getRawType() != Instance.class);
private static final Map<Type, Type> REPLACED_TYPES = new HashMap<>();
static {
@@ -79,44 +67,24 @@ public class MPJWTCDIExtension implements Extension {
final Set<Type> types = injectionPoints.stream()
.filter(NOT_PROVIDERS)
.filter(NOT_INSTANCES)
- .map(new Function<InjectionPoint, Type>() {
- @Override
- public Type apply(final InjectionPoint ip) {
- return REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType());
- }
- })
+ .map(ip -> REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType()))
.collect(Collectors.<Type>toSet());
final Set<Type> providerTypes = injectionPoints.stream()
.filter(NOT_PROVIDERS.negate())
- .map(new Function<InjectionPoint, Type>() {
- @Override
- public Type apply(final InjectionPoint ip) {
- return ((ParameterizedType) ip.getType()).getActualTypeArguments()[0];
- }
- })
+ .map(ip -> ((ParameterizedType) ip.getType()).getActualTypeArguments()[0])
.collect(Collectors.<Type>toSet());
final Set<Type> instanceTypes = injectionPoints.stream()
.filter(NOT_INSTANCES.negate())
- .map(new Function<InjectionPoint, Type>() {
- @Override
- public Type apply(final InjectionPoint ip) {
- return ((ParameterizedType) ip.getType()).getActualTypeArguments()[0];
- }
- })
+ .map(ip -> ((ParameterizedType) ip.getType()).getActualTypeArguments()[0])
.collect(Collectors.<Type>toSet());
types.addAll(providerTypes);
types.addAll(instanceTypes);
types.stream()
- .map(new Function<Type, ClaimBean>() {
- @Override
- public ClaimBean apply(final Type type) {
- return new ClaimBean<>(bm, type);
- }
- })
+ .map(type -> new ClaimBean<>(bm, type))
.forEach(new Consumer<ClaimBean>() {
@Override
public void accept(final ClaimBean claimBean) {
@@ -129,7 +97,6 @@ public class MPJWTCDIExtension implements Extension {
bbd.addAnnotatedType(beanManager.createAnnotatedType(JsonbProducer.class));
bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTFilter.class));
bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTInitializer.class));
- bbd.addAnnotatedType(beanManager.createAnnotatedType(JWTAuthContextInfoProvider.class));
bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTProducer.class));
}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfoProvider.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfoProvider.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfoProvider.java
deleted file mode 100644
index 9247e04..0000000
--- a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfoProvider.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomee.microprofile.jwt.config;
-
-import javax.enterprise.context.Dependent;
-import javax.enterprise.inject.Produces;
-import java.security.KeyFactory;
-import java.security.NoSuchAlgorithmException;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.Base64;
-import java.util.Optional;
-
-@Dependent
-public class JWTAuthContextInfoProvider {
-
- @Produces
- Optional<JWTAuthContextInfo> getOptionalContextInfo() throws NoSuchAlgorithmException, InvalidKeySpecException {
- JWTAuthContextInfo contextInfo = new JWTAuthContextInfo();
-
- // todo use MP Config to load the configuration
- contextInfo.setIssuedBy("https://server.example.com");
-
- final String pemEncoded = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq" +
- "Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR" +
- "TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e" +
- "UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9" +
- "AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn" +
- "sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x" +
- "nQIDAQAB";
- byte[] encodedBytes = Base64.getDecoder().decode(pemEncoded);
-
- final X509EncodedKeySpec spec = new X509EncodedKeySpec(encodedBytes);
- final KeyFactory kf = KeyFactory.getInstance("RSA");
- final RSAPublicKey pk = (RSAPublicKey) kf.generatePublic(spec);
-
- contextInfo.setSignerKey(pk);
-
- return Optional.of(contextInfo);
- }
-
- @Produces
- JWTAuthContextInfo getContextInfo() throws InvalidKeySpecException, NoSuchAlgorithmException {
- return getOptionalContextInfo().get();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/tck/microprofile-tck/jwt/src/main/java/org/apache/tomee/microprofile/jwt/JWTAuthContextInfoProvider.java
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/src/main/java/org/apache/tomee/microprofile/jwt/JWTAuthContextInfoProvider.java b/tck/microprofile-tck/jwt/src/main/java/org/apache/tomee/microprofile/jwt/JWTAuthContextInfoProvider.java
new file mode 100644
index 0000000..bf0a07f
--- /dev/null
+++ b/tck/microprofile-tck/jwt/src/main/java/org/apache/tomee/microprofile/jwt/JWTAuthContextInfoProvider.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt;
+
+import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Produces;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+import java.util.Optional;
+
+@Dependent
+public class JWTAuthContextInfoProvider {
+
+ @Produces
+ Optional<JWTAuthContextInfo> getOptionalContextInfo() throws NoSuchAlgorithmException, InvalidKeySpecException {
+ JWTAuthContextInfo contextInfo = new JWTAuthContextInfo();
+
+ // todo use MP Config to load the configuration
+ contextInfo.setIssuedBy("https://server.example.com");
+
+ final String pemEncoded = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq" +
+ "Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR" +
+ "TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e" +
+ "UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9" +
+ "AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn" +
+ "sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x" +
+ "nQIDAQAB";
+ byte[] encodedBytes = Base64.getDecoder().decode(pemEncoded);
+
+ final X509EncodedKeySpec spec = new X509EncodedKeySpec(encodedBytes);
+ final KeyFactory kf = KeyFactory.getInstance("RSA");
+ final RSAPublicKey pk = (RSAPublicKey) kf.generatePublic(spec);
+
+ contextInfo.setSignerKey(pk);
+
+ return Optional.of(contextInfo);
+ }
+
+ @Produces
+ JWTAuthContextInfo getContextInfo() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ return getOptionalContextInfo().get();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java b/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java
index cf4e837..f5f2183 100644
--- a/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java
+++ b/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java
@@ -68,7 +68,8 @@ public class AppDeploymentExtension implements LoadableExtension {
if (!(appArchive instanceof WebArchive)) {
return;
}
- WebArchive war = WebArchive.class.cast(appArchive);
+ final WebArchive war = WebArchive.class.cast(appArchive);
+ war.addClass(JWTAuthContextInfoProvider.class);
log.info("Augmented war: \n"+war.toString(true));
}
[3/8] tomee git commit: Missing files from previous commit
Posted by jl...@apache.org.
Missing files from previous commit
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/def443a4
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/def443a4
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/def443a4
Branch: refs/heads/fb_tomee8
Commit: def443a4174a402ee25a30325d4695c5c995b2ac
Parents: 82670f9
Author: Jean-Louis Monteiro <je...@gmail.com>
Authored: Tue Apr 17 22:31:41 2018 +0200
Committer: Jean-Louis Monteiro <je...@gmail.com>
Committed: Tue Apr 17 22:31:41 2018 +0200
----------------------------------------------------------------------
mp-jwt/pom.xml | 79 ++++
.../tomee/microprofile/jwt/MPJWTFilter.java | 271 ++++++++++++++
.../microprofile/jwt/MPJWTInitializer.java | 64 ++++
.../tomee/microprofile/jwt/ParseException.java | 32 ++
.../tomee/microprofile/jwt/cdi/ClaimBean.java | 373 +++++++++++++++++++
.../jwt/cdi/ClaimInjectionPoint.java | 70 ++++
.../microprofile/jwt/cdi/ClaimValueWrapper.java | 53 +++
.../microprofile/jwt/cdi/DefaultLiteral.java | 24 ++
.../microprofile/jwt/cdi/JsonbProducer.java | 46 +++
.../microprofile/jwt/cdi/MPJWTCDIExtension.java | 136 +++++++
.../microprofile/jwt/cdi/MPJWTProducer.java | 49 +++
.../jwt/config/JWTAuthContextInfo.java | 67 ++++
.../jwt/config/JWTAuthContextInfoProvider.java | 61 +++
.../jwt/jaxrs/MPJWPProviderRegistration.java | 36 ++
.../MPJWTSecurityAnnotationsInterceptor.java | 57 +++
...TSecurityAnnotationsInterceptorsFeature.java | 144 +++++++
.../principal/DefaultJWTCallerPrincipal.java | 360 ++++++++++++++++++
.../DefaultJWTCallerPrincipalFactory.java | 92 +++++
.../jwt/principal/JWTCallerPrincipal.java | 59 +++
.../principal/JWTCallerPrincipalFactory.java | 129 +++++++
.../META-INF/org.apache.openejb.extension | 1 +
.../javax.enterprise.inject.spi.Extension | 1 +
.../javax.servlet.ServletContainerInitializer | 1 +
...file.jwt.principal.JWTCallerPrincipalFactory | 1 +
tck/microprofile-tck/jwt/pom.xml | 197 ++++++++++
.../jwt/AppDeploymentExtension.java | 76 ++++
....jboss.arquillian.core.spi.LoadableExtension | 1 +
.../jwt/src/test/resources/arquillian.xml | 39 ++
.../jwt/src/test/resources/dev.xml | 93 +++++
29 files changed, 2612 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/pom.xml
----------------------------------------------------------------------
diff --git a/mp-jwt/pom.xml b/mp-jwt/pom.xml
new file mode 100644
index 0000000..a6cae6a
--- /dev/null
+++ b/mp-jwt/pom.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<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">
+ <parent>
+ <artifactId>tomee-project</artifactId>
+ <groupId>org.apache.tomee</groupId>
+ <version>8.0.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>mp-jwt</artifactId>
+ <packaging>jar</packaging>
+ <name>OpenEJB :: Microprofile JWT</name>
+
+ <properties>
+ <mp-jwt.version>1.1-SNAPSHOT</mp-jwt.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>javaee-api</artifactId>
+ <version>${version.javaee-api}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>openejb-core</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>openejb-cxf-rs</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.bitbucket.b_c</groupId>
+ <artifactId>jose4j</artifactId>
+ <version>0.6.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.johnzon</groupId>
+ <artifactId>johnzon-jsonb</artifactId>
+ <version>${johnzon.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat</groupId>
+ <artifactId>tomcat-catalina</artifactId>
+ <version>${tomcat.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.microprofile.jwt</groupId>
+ <artifactId>microprofile-jwt-auth-api</artifactId>
+ <version>${mp-jwt.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+
+</project>
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java
new file mode 100644
index 0000000..a7b47d3
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java
@@ -0,0 +1,271 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt;
+
+import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo;
+import org.apache.tomee.microprofile.jwt.principal.JWTCallerPrincipalFactory;
+import org.eclipse.microprofile.jwt.JsonWebToken;
+
+import javax.inject.Inject;
+import javax.security.auth.Subject;
+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.annotation.WebFilter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+// async is supported because we only need to do work on the way in
+@WebFilter(asyncSupported = true, urlPatterns = "/*")
+public class MPJWTFilter implements Filter {
+
+ @Inject
+ private JWTAuthContextInfo authContextInfo;
+
+ @Override
+ public void init(final FilterConfig filterConfig) throws ServletException {
+ // nothing so far
+
+ }
+
+ @Override
+ public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
+
+ final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+
+ // now wrap the httpServletRequest and override the principal so CXF can propagate into the SecurityContext
+ try {
+ chain.doFilter(new MPJWTServletRequestWrapper(httpServletRequest, authContextInfo), response);
+
+ } catch (final Exception e) {
+ // this is an alternative to the @Provider bellow which requires registration on the fly
+ // or users to add it into their webapp for scanning or into the Application itself
+ if (MPJWTException.class.isInstance(e)) {
+ final MPJWTException jwtException = MPJWTException.class.cast(e);
+ HttpServletResponse.class.cast(response).sendError(jwtException.getStatus(), jwtException.getMessage());
+ }
+
+ if (MPJWTException.class.isInstance(e.getCause())) {
+ final MPJWTException jwtException = MPJWTException.class.cast(e.getCause());
+ HttpServletResponse.class.cast(response).sendError(jwtException.getStatus(), jwtException.getMessage());
+ }
+
+ }
+
+ }
+
+ @Override
+ public void destroy() {
+ // nothing to do
+ }
+
+ private static Function<HttpServletRequest, JsonWebToken> token(final HttpServletRequest httpServletRequest, final JWTAuthContextInfo authContextInfo) {
+
+ return new Function<HttpServletRequest, JsonWebToken>() {
+
+ private JsonWebToken jsonWebToken;
+
+ @Override
+ public JsonWebToken apply(final HttpServletRequest request) {
+
+ // not sure it's worth having synchronization inside a single request
+ // worth case, we would parse and validate the token twice
+ if (jsonWebToken != null) {
+ return jsonWebToken;
+ }
+
+ final String authorizationHeader = httpServletRequest.getHeader("Authorization");
+ if (authorizationHeader == null || authorizationHeader.isEmpty()) {
+ throw new MissingAuthorizationHeaderException();
+ }
+
+ if (!authorizationHeader.toLowerCase(Locale.ENGLISH).startsWith("bearer ")) {
+ throw new BadAuthorizationPrefixException(authorizationHeader);
+ }
+
+ final String token = authorizationHeader.substring("bearer ".length());
+ try {
+ jsonWebToken = validate(token, authContextInfo);
+
+ } catch (final ParseException e) {
+ throw new InvalidTokenException(token, e);
+ }
+
+ return jsonWebToken;
+
+ }
+ };
+
+ }
+
+ private static JsonWebToken validate(final String bearerToken, final JWTAuthContextInfo authContextInfo) throws ParseException {
+ JWTCallerPrincipalFactory factory = JWTCallerPrincipalFactory.instance();
+ return factory.parse(bearerToken, authContextInfo);
+ }
+
+ public static class MPJWTServletRequestWrapper extends HttpServletRequestWrapper {
+
+ private final Function<HttpServletRequest, JsonWebToken> tokenFunction;
+ private final HttpServletRequest request;
+
+ /**
+ * Constructs a request object wrapping the given request.
+ *
+ * @param request The request to wrap
+ * @param authContextInfo the context configuration to validate the token
+ * @throws IllegalArgumentException if the request is null
+ */
+ public MPJWTServletRequestWrapper(final HttpServletRequest request, final JWTAuthContextInfo authContextInfo) {
+ super(request);
+ this.request = request;
+ tokenFunction = token(request, authContextInfo);
+
+ // this is so that the MPJWTProducer can find the function and apply it if necessary
+ request.setAttribute(JsonWebToken.class.getName(), tokenFunction);
+ request.setAttribute("javax.security.auth.subject.callable", (Callable<Subject>) new Callable<Subject>() {
+ @Override
+ public Subject call() throws Exception {
+ final Set<Principal> principals = new LinkedHashSet<>();
+ final JsonWebToken namePrincipal = tokenFunction.apply(request);
+ principals.add(namePrincipal);
+ principals.addAll(namePrincipal.getGroups().stream().map(new Function<String, Principal>() {
+ @Override
+ public Principal apply(final String role) {
+ return (Principal) new Principal() {
+ @Override
+ public String getName() {
+ return role;
+ }
+ };
+ }
+ }).collect(Collectors.<Principal>toList()));
+ return new Subject(true, principals, Collections.emptySet(), Collections.emptySet());
+ }
+ });
+ }
+
+ @Override
+ public Principal getUserPrincipal() {
+ return tokenFunction.apply(request);
+ }
+
+ @Override
+ public boolean isUserInRole(String role) {
+ final JsonWebToken jsonWebToken = tokenFunction.apply(request);
+ return jsonWebToken.getGroups().contains(role);
+ }
+
+ @Override
+ public String getAuthType() {
+ return "MP-JWT";
+ }
+
+ }
+
+ private static abstract class MPJWTException extends RuntimeException {
+
+ public MPJWTException() {
+ super();
+ }
+
+ public MPJWTException(final Throwable cause) {
+ super(cause);
+ }
+
+ public abstract int getStatus();
+
+ public abstract String getMessage();
+ }
+
+ private static class MissingAuthorizationHeaderException extends MPJWTException {
+
+ @Override
+ public int getStatus() {
+ return HttpServletResponse.SC_UNAUTHORIZED;
+ }
+
+ @Override
+ public String getMessage() {
+ return "No authorization header provided. Can't validate the JWT.";
+ }
+ }
+
+ private static class BadAuthorizationPrefixException extends MPJWTException {
+
+ private String authorizationHeader;
+
+ public BadAuthorizationPrefixException(final String authorizationHeader) {
+ this.authorizationHeader = authorizationHeader;
+ }
+
+ @Override
+ public int getStatus() {
+ return HttpServletResponse.SC_UNAUTHORIZED;
+ }
+
+ @Override
+ public String getMessage() {
+ return "Authorization header does not use the Bearer prefix. Can't validate header " + authorizationHeader;
+ }
+ }
+
+ private static class InvalidTokenException extends MPJWTException {
+
+ private final String token;
+
+ public InvalidTokenException(final String token, final Throwable cause) {
+ super(cause);
+ this.token = token;
+ }
+
+ @Override
+ public int getStatus() {
+ return HttpServletResponse.SC_UNAUTHORIZED;
+ }
+
+ @Override
+ public String getMessage() {
+ return "Invalid or not parsable JWT " + token; // we might want to break down the exceptions so we can have more messages.
+ }
+ }
+
+ @Provider // would be the ideal but not automatically registered
+ public static class MPJWTExceptionMapper implements ExceptionMapper<MPJWTException> {
+
+ @Override
+ public Response toResponse(final MPJWTException exception) {
+ return Response.status(exception.getStatus()).entity(exception.getMessage()).build();
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTInitializer.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTInitializer.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTInitializer.java
new file mode 100644
index 0000000..cede7dc
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTInitializer.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt;
+
+import org.eclipse.microprofile.auth.LoginConfig;
+
+import javax.servlet.FilterRegistration;
+import javax.servlet.ServletContainerInitializer;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.HandlesTypes;
+import javax.ws.rs.core.Application;
+import java.util.Set;
+
+/**
+ * Responsible for adding the filter into the chain and doing all other initialization
+ */
+@HandlesTypes(LoginConfig.class)
+public class MPJWTInitializer implements ServletContainerInitializer {
+
+ @Override
+ public void onStartup(final Set<Class<?>> classes, final ServletContext ctx) throws ServletException {
+
+ if (classes == null || classes.isEmpty()) {
+ return; // no classe having @LoginConfig on it
+ }
+
+ for (Class<?> clazz : classes) {
+ final LoginConfig loginConfig = clazz.getAnnotation(LoginConfig.class);
+
+ if (loginConfig.authMethod() == null && !"MP-JWT".equals(loginConfig.authMethod())) {
+ continue;
+ }
+
+ if (!Application.class.isAssignableFrom(clazz)) {
+ continue;
+ // do we really want Application?
+ // See https://github.com/eclipse/microprofile-jwt-auth/issues/70 to clarify this point
+ }
+
+ final FilterRegistration.Dynamic mpJwtFilter = ctx.addFilter("mp-jwt-filter", MPJWTFilter.class);
+ mpJwtFilter.setAsyncSupported(true);
+ mpJwtFilter.addMappingForUrlPatterns(null, false, "/*");
+
+ break; // no need to add it more than once
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/ParseException.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/ParseException.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/ParseException.java
new file mode 100644
index 0000000..d9572d5
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/ParseException.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt;
+
+/**
+ * The exception thrown when
+ */
+public class ParseException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public ParseException(final String message) {
+ super(message);
+ }
+
+ public ParseException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimBean.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimBean.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimBean.java
new file mode 100644
index 0000000..be83a9b
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimBean.java
@@ -0,0 +1,373 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.cdi;
+
+import org.eclipse.microprofile.jwt.Claim;
+import org.eclipse.microprofile.jwt.ClaimValue;
+import org.eclipse.microprofile.jwt.Claims;
+import org.eclipse.microprofile.jwt.JsonWebToken;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.Instance;
+import javax.enterprise.inject.Vetoed;
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.PassivationCapable;
+import javax.enterprise.util.AnnotationLiteral;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.json.Json;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+import javax.json.bind.Jsonb;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Supplier;
+import java.util.logging.Logger;
+
+@Vetoed
+public class ClaimBean<T> implements Bean<T>, PassivationCapable {
+
+ private static final Logger logger = Logger.getLogger(MPJWTCDIExtension.class.getName());
+
+ private static final Set<Annotation> QUALIFIERS = new HashSet<>();
+
+ static {
+ QUALIFIERS.add(new ClaimLiteral());
+ }
+
+ @Inject
+ private Jsonb jsonb;
+
+ private final BeanManager bm;
+ private final Class rawType;
+ private final Set<Type> types;
+ private final String id;
+ private final Class<? extends Annotation> scope;
+
+ public ClaimBean(final BeanManager bm, final Type type) {
+ this.bm = bm;
+ types = new HashSet<>();
+ types.add(type);
+ rawType = getRawType(type);
+ this.id = "ClaimBean_" + types;
+ scope = Dependent.class;
+ }
+
+ private Class getRawType(final Type type) {
+ if (Class.class.isInstance(type)) {
+ return Class.class.cast(type);
+
+ } else if (ParameterizedType.class.isInstance(type)) {
+ final ParameterizedType paramType = ParameterizedType.class.cast(type);
+ return Class.class.cast(paramType.getRawType());
+ }
+
+ throw new UnsupportedOperationException("Unsupported type " + type);
+ }
+
+
+ @Override
+ public Set<InjectionPoint> getInjectionPoints() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ return rawType;
+ }
+
+ @Override
+ public boolean isNullable() {
+ return false;
+ }
+
+ @Override
+ public void destroy(final T instance, final CreationalContext<T> context) {
+ logger.finest("Destroying CDI Bean for type " + types.iterator().next());
+ }
+
+ @Override
+ public Set<Type> getTypes() {
+ return types;
+ }
+
+ @Override
+ public Set<Annotation> getQualifiers() {
+ return QUALIFIERS;
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return scope;
+ }
+
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ @Override
+ public Set<Class<? extends Annotation>> getStereotypes() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public boolean isAlternative() {
+ return false;
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public T create(final CreationalContext<T> context) {
+ logger.finest("Creating CDI Bean for type " + types.iterator().next());
+ final InjectionPoint ip = (InjectionPoint) bm.getInjectableReference(new ClaimInjectionPoint(this), context);
+ if (ip == null) {
+ throw new IllegalStateException("Could not retrieve InjectionPoint for type " + types.iterator().next());
+ }
+
+ final Annotated annotated = ip.getAnnotated();
+ final Claim claim = annotated.getAnnotation(Claim.class);
+ final String key = getClaimKey(claim);
+
+ logger.finest(String.format("Found Claim injection with name=%s and for %s", key, ip.toString()));
+
+ if (ParameterizedType.class.isInstance(annotated.getBaseType())) {
+ final ParameterizedType paramType = ParameterizedType.class.cast(annotated.getBaseType());
+ final Type rawType = paramType.getRawType();
+ if (Class.class.isInstance(rawType) && paramType.getActualTypeArguments().length == 1) {
+
+ final Class<?> rawTypeClass = ((Class<?>) rawType);
+
+ // handle Provider<T>
+ if (rawTypeClass.isAssignableFrom(Provider.class)) {
+ final Type providerType = paramType.getActualTypeArguments()[0];
+ if (ParameterizedType.class.isInstance(providerType) && isOptional(ParameterizedType.class.cast(providerType))) {
+ return (T) Optional.ofNullable(getClaimValue(key));
+ }
+ return getClaimValue(key);
+ }
+
+ // handle Instance<T>
+ if (rawTypeClass.isAssignableFrom(Instance.class)) {
+ final Type instanceType = paramType.getActualTypeArguments()[0];
+ if (ParameterizedType.class.isInstance(instanceType) && isOptional(ParameterizedType.class.cast(instanceType))) {
+ return (T) Optional.ofNullable(getClaimValue(key));
+ }
+ return getClaimValue(key);
+ }
+
+ // handle ClaimValue<T>
+ if (rawTypeClass.isAssignableFrom(ClaimValue.class)) {
+ final Type claimValueType = paramType.getActualTypeArguments()[0];
+
+ final ClaimValueWrapper claimValueWrapper = new ClaimValueWrapper(key);
+ if (ParameterizedType.class.isInstance(claimValueType) && isOptional(ParameterizedType.class.cast(claimValueType))) {
+ claimValueWrapper.setValue(new Supplier() {
+ @Override
+ public Object get() {
+ final T claimValue = ClaimBean.this.getClaimValue(key);
+ return Optional.ofNullable(claimValue);
+ }
+ });
+
+ } else if (ParameterizedType.class.isInstance(claimValueType) && isSet(ParameterizedType.class.cast(claimValueType))) {
+ claimValueWrapper.setValue(new Supplier() {
+ @Override
+ public Object get() {
+ final T claimValue = ClaimBean.this.getClaimValue(key);
+ return claimValue;
+ }
+ });
+
+ } else if (ParameterizedType.class.isInstance(claimValueType) && isList(ParameterizedType.class.cast(claimValueType))) {
+ claimValueWrapper.setValue(new Supplier() {
+ @Override
+ public Object get() {
+ final T claimValue = ClaimBean.this.getClaimValue(key);
+ return claimValue;
+ }
+ });
+
+ } else if (Class.class.isInstance(claimValueType)) {
+ claimValueWrapper.setValue(new Supplier() {
+ @Override
+ public Object get() {
+ final T claimValue = ClaimBean.this.getClaimValue(key);
+ return claimValue;
+ }
+ });
+
+ } else {
+ throw new IllegalArgumentException("Unsupported ClaimValue type " + claimValueType.toString());
+ }
+
+ return (T) claimValueWrapper;
+ }
+
+ // handle Optional<T>
+ if (rawTypeClass.isAssignableFrom(Optional.class)) {
+ return getClaimValue(key);
+ }
+
+ // handle Set<T>
+ if (rawTypeClass.isAssignableFrom(Set.class)) {
+ return getClaimValue(key);
+ }
+
+ // handle List<T>
+ if (rawTypeClass.isAssignableFrom(List.class)) {
+ return getClaimValue(key);
+ }
+ }
+
+ } else if (annotated.getBaseType().getTypeName().startsWith("javax.json.Json")) {
+ // handle JsonValue<T> (number, string, etc)
+ return (T) toJson(key);
+
+ } else {
+ // handle Raw types
+ return getClaimValue(key);
+ }
+
+ throw new IllegalStateException("Unhandled Claim type " + annotated.getBaseType());
+ }
+
+ public static String getClaimKey(final Claim claim) {
+ return claim.standard() == Claims.UNKNOWN ? claim.value() : claim.standard().name();
+ }
+
+ private T getClaimValue(final String name) {
+ final Bean<?> bean = bm.resolve(bm.getBeans(JsonWebToken.class));
+ JsonWebToken jsonWebToken = null;
+ if (RequestScoped.class.equals(bean.getScope())) {
+ jsonWebToken = JsonWebToken.class.cast(bm.getReference(bean, JsonWebToken.class, null));
+ }
+ if (jsonWebToken == null || !bean.getScope().equals(RequestScoped.class)) {
+ logger.warning(String.format("Can't retrieve claim %s. No active principal.", name));
+ return null;
+ }
+
+ final Optional<T> claimValue = jsonWebToken.claim(name);
+ logger.finest(String.format("Found ClaimValue=%s for name=%s", claimValue, name));
+ return claimValue.orElse(null);
+ }
+
+ private JsonValue toJson(final String name) {
+ final T claimValue = getClaimValue(name);
+ return wrapValue(claimValue);
+ }
+
+ private static final String TMP = "tmp";
+
+ private JsonValue wrapValue(final Object value) {
+ JsonValue jsonValue = null;
+
+ if (JsonValue.class.isInstance(value)) {
+ // This may already be a JsonValue
+ jsonValue = JsonValue.class.cast(value);
+
+ } else if (String.class.isInstance(value)) {
+ jsonValue = Json.createObjectBuilder()
+ .add(TMP, value.toString())
+ .build()
+ .getJsonString(TMP);
+
+ } else if (Number.class.isInstance(value)) {
+ final Number number = Number.class.cast(value);
+ if ((Long.class.isInstance(number)) || (Integer.class.isInstance(number))) {
+ jsonValue = Json.createObjectBuilder()
+ .add(TMP, number.longValue())
+ .build()
+ .getJsonNumber(TMP);
+
+ } else {
+ jsonValue = Json.createObjectBuilder()
+ .add(TMP, number.doubleValue())
+ .build()
+ .getJsonNumber(TMP);
+ }
+
+ } else if (Boolean.class.isInstance(value)) {
+ final Boolean flag = Boolean.class.cast(value);
+ jsonValue = flag ? JsonValue.TRUE : JsonValue.FALSE;
+
+ } else if (Collection.class.isInstance(value)) {
+ final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
+ final Collection list = Collection.class.cast(value);
+
+ for (Object element : list) {
+ if (String.class.isInstance(element)) {
+ arrayBuilder.add(element.toString());
+
+ } else {
+ final JsonValue jvalue = wrapValue(element);
+ arrayBuilder.add(jvalue);
+ }
+ }
+ jsonValue = arrayBuilder.build();
+
+ } else if (Map.class.isInstance(value)) {
+ jsonValue = jsonb.fromJson(jsonb.toJson(value), JsonObject.class);
+
+ }
+ return jsonValue;
+ }
+
+ private boolean isOptional(final ParameterizedType type) {
+ return ((Class) type.getRawType()).isAssignableFrom(Optional.class);
+ }
+
+ private boolean isSet(final ParameterizedType type) {
+ return ((Class) type.getRawType()).isAssignableFrom(Set.class);
+ }
+
+ private boolean isList(final ParameterizedType type) {
+ return ((Class) type.getRawType()).isAssignableFrom(List.class);
+ }
+
+ private static class ClaimLiteral extends AnnotationLiteral<Claim> implements Claim {
+
+ @Override
+ public String value() {
+ return "";
+ }
+
+ @Override
+ public Claims standard() {
+ return Claims.UNKNOWN;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimInjectionPoint.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimInjectionPoint.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimInjectionPoint.java
new file mode 100644
index 0000000..2f1fd3d
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimInjectionPoint.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.cdi;
+
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.InjectionPoint;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Member;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.Set;
+
+public class ClaimInjectionPoint implements InjectionPoint {
+
+ private final Bean bean;
+
+ public ClaimInjectionPoint(final Bean bean) {
+ this.bean = bean;
+ }
+
+ @Override
+ public boolean isTransient() {
+ return false;
+ }
+
+ @Override
+ public boolean isDelegate() {
+ return false;
+ }
+
+ @Override
+ public Type getType() {
+ return InjectionPoint.class;
+ }
+
+ @Override
+ public Set<Annotation> getQualifiers() {
+ return Collections.<Annotation>singleton(DefaultLiteral.INSTANCE);
+ }
+
+ @Override
+ public Member getMember() {
+ return null;
+ }
+
+ @Override
+ public Bean<?> getBean() {
+ return bean;
+ }
+
+ @Override
+ public Annotated getAnnotated() {
+ return null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimValueWrapper.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimValueWrapper.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimValueWrapper.java
new file mode 100644
index 0000000..2836abd
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimValueWrapper.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.cdi;
+
+import org.eclipse.microprofile.jwt.ClaimValue;
+
+import java.util.function.Supplier;
+
+public class ClaimValueWrapper<T> implements ClaimValue<T> {
+
+ private final String name;
+ private Supplier<T> value;
+
+ public ClaimValueWrapper(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public T getValue() {
+ return value.get();
+ }
+
+ void setValue(final Supplier<T> value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "ClaimValueWrapper{" +
+ "name='" + name + '\'' +
+ ", value=" + value.get() +
+ '}';
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/DefaultLiteral.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/DefaultLiteral.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/DefaultLiteral.java
new file mode 100644
index 0000000..273ff96
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/DefaultLiteral.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.cdi;
+
+import javax.enterprise.inject.Default;
+import javax.enterprise.util.AnnotationLiteral;
+
+public class DefaultLiteral extends AnnotationLiteral<Default> implements Default {
+ public static final Default INSTANCE = new DefaultLiteral();
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/JsonbProducer.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/JsonbProducer.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/JsonbProducer.java
new file mode 100644
index 0000000..53a9088
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/JsonbProducer.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.cdi;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Disposes;
+import javax.enterprise.inject.Produces;
+import javax.json.bind.Jsonb;
+import javax.json.bind.spi.JsonbProvider;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+@ApplicationScoped
+// todo add a qualifier here so we isolate our instance from what applications would do
+public class JsonbProducer {
+
+ private static final Logger log = Logger.getLogger(MPJWTCDIExtension.class.getName());
+
+ @Produces
+ public Jsonb create() {
+ return JsonbProvider.provider().create().build();
+ }
+
+ public void close(@Disposes final Jsonb jsonb) {
+ try {
+ jsonb.close();
+
+ } catch (final Exception e) {
+ log.log(Level.WARNING, e.getMessage(), e);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
new file mode 100644
index 0000000..051f05a
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.cdi;
+
+import org.apache.tomee.microprofile.jwt.MPJWTFilter;
+import org.apache.tomee.microprofile.jwt.MPJWTInitializer;
+import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfoProvider;
+import org.eclipse.microprofile.jwt.Claim;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Instance;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.ProcessInjectionPoint;
+import javax.inject.Provider;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+public class MPJWTCDIExtension implements Extension {
+
+ private static final Predicate<InjectionPoint> NOT_PROVIDERS = new Predicate<InjectionPoint>() {
+ @Override
+ public boolean test(final InjectionPoint ip) {
+ return (Class.class.isInstance(ip.getType())) || (ParameterizedType.class.isInstance(ip.getType()) && ((ParameterizedType) ip.getType()).getRawType() != Provider.class);
+ }
+ };
+ private static final Predicate<InjectionPoint> NOT_INSTANCES = new Predicate<InjectionPoint>() {
+ @Override
+ public boolean test(final InjectionPoint ip) {
+ return (Class.class.isInstance(ip.getType())) || (ParameterizedType.class.isInstance(ip.getType()) && ((ParameterizedType) ip.getType()).getRawType() != Instance.class);
+ }
+ };
+ private static final Map<Type, Type> REPLACED_TYPES = new HashMap<>();
+
+ static {
+ REPLACED_TYPES.put(double.class, Double.class);
+ REPLACED_TYPES.put(int.class, Integer.class);
+ REPLACED_TYPES.put(float.class, Float.class);
+ REPLACED_TYPES.put(long.class, Long.class);
+ REPLACED_TYPES.put(boolean.class, Boolean.class);
+ }
+
+ private Set<InjectionPoint> injectionPoints = new HashSet<>();
+
+ public void collectConfigProducer(@Observes final ProcessInjectionPoint<?, ?> pip) {
+ final Claim claim = pip.getInjectionPoint().getAnnotated().getAnnotation(Claim.class);
+ if (claim != null) {
+ injectionPoints.add(pip.getInjectionPoint());
+ }
+ }
+
+ public void registerClaimProducer(@Observes final AfterBeanDiscovery abd, final BeanManager bm) {
+
+ final Set<Type> types = injectionPoints.stream()
+ .filter(NOT_PROVIDERS)
+ .filter(NOT_INSTANCES)
+ .map(new Function<InjectionPoint, Type>() {
+ @Override
+ public Type apply(final InjectionPoint ip) {
+ return REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType());
+ }
+ })
+ .collect(Collectors.<Type>toSet());
+
+ final Set<Type> providerTypes = injectionPoints.stream()
+ .filter(NOT_PROVIDERS.negate())
+ .map(new Function<InjectionPoint, Type>() {
+ @Override
+ public Type apply(final InjectionPoint ip) {
+ return ((ParameterizedType) ip.getType()).getActualTypeArguments()[0];
+ }
+ })
+ .collect(Collectors.<Type>toSet());
+
+ final Set<Type> instanceTypes = injectionPoints.stream()
+ .filter(NOT_INSTANCES.negate())
+ .map(new Function<InjectionPoint, Type>() {
+ @Override
+ public Type apply(final InjectionPoint ip) {
+ return ((ParameterizedType) ip.getType()).getActualTypeArguments()[0];
+ }
+ })
+ .collect(Collectors.<Type>toSet());
+
+ types.addAll(providerTypes);
+ types.addAll(instanceTypes);
+
+ types.stream()
+ .map(new Function<Type, ClaimBean>() {
+ @Override
+ public ClaimBean apply(final Type type) {
+ return new ClaimBean<>(bm, type);
+ }
+ })
+ .forEach(new Consumer<ClaimBean>() {
+ @Override
+ public void accept(final ClaimBean claimBean) {
+ abd.addBean(claimBean);
+ }
+ });
+ }
+
+ public void observeBeforeBeanDiscovery(@Observes final BeforeBeanDiscovery bbd, final BeanManager beanManager) {
+ bbd.addAnnotatedType(beanManager.createAnnotatedType(JsonbProducer.class));
+ bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTFilter.class));
+ bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTInitializer.class));
+ bbd.addAnnotatedType(beanManager.createAnnotatedType(JWTAuthContextInfoProvider.class));
+ bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTProducer.class));
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTProducer.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTProducer.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTProducer.java
new file mode 100644
index 0000000..42034b9
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTProducer.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.cdi;
+
+import org.eclipse.microprofile.jwt.JsonWebToken;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.Produces;
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+import java.util.Objects;
+import java.util.function.Function;
+
+@ApplicationScoped
+public class MPJWTProducer {
+
+ @Inject
+ private HttpServletRequest httpServletRequest;
+
+ @Produces
+ @RequestScoped
+ public JsonWebToken currentPrincipal() {
+ Objects.requireNonNull(httpServletRequest, "HTTP Servlet Request is required to produce a JSonWebToken principal.");
+
+ // not very beautiful, but avoids having the MPJWTFilter setting the request or the principal in a thread local
+ // CDI integration already has one - dunno which approach is the best for now
+ final Object tokenAttribute = httpServletRequest.getAttribute(JsonWebToken.class.getName());
+ if (Function.class.isInstance(tokenAttribute)) {
+ return (JsonWebToken) Function.class.cast(tokenAttribute).apply(httpServletRequest);
+ }
+
+ return null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfo.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfo.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfo.java
new file mode 100644
index 0000000..a969515
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfo.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.config;
+
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * The public key and expected issuer needed to validate a token.
+ */
+public class JWTAuthContextInfo {
+
+ private RSAPublicKey signerKey;
+ private String issuedBy;
+ private int expGracePeriodSecs = 60;
+
+ public JWTAuthContextInfo() {
+ }
+
+ public JWTAuthContextInfo(final RSAPublicKey signerKey, final String issuedBy) {
+ this.signerKey = signerKey;
+ this.issuedBy = issuedBy;
+ }
+
+ public JWTAuthContextInfo(final JWTAuthContextInfo orig) {
+ this.signerKey = orig.signerKey;
+ this.issuedBy = orig.issuedBy;
+ this.expGracePeriodSecs = orig.expGracePeriodSecs;
+ }
+
+ public RSAPublicKey getSignerKey() {
+ return signerKey;
+ }
+
+ public void setSignerKey(final RSAPublicKey signerKey) {
+ this.signerKey = signerKey;
+ }
+
+ public String getIssuedBy() {
+ return issuedBy;
+ }
+
+ public void setIssuedBy(final String issuedBy) {
+ this.issuedBy = issuedBy;
+ }
+
+ public int getExpGracePeriodSecs() {
+ return expGracePeriodSecs;
+ }
+
+ public void setExpGracePeriodSecs(final int expGracePeriodSecs) {
+ this.expGracePeriodSecs = expGracePeriodSecs;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfoProvider.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfoProvider.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfoProvider.java
new file mode 100644
index 0000000..9247e04
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfoProvider.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.config;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Produces;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+import java.util.Optional;
+
+@Dependent
+public class JWTAuthContextInfoProvider {
+
+ @Produces
+ Optional<JWTAuthContextInfo> getOptionalContextInfo() throws NoSuchAlgorithmException, InvalidKeySpecException {
+ JWTAuthContextInfo contextInfo = new JWTAuthContextInfo();
+
+ // todo use MP Config to load the configuration
+ contextInfo.setIssuedBy("https://server.example.com");
+
+ final String pemEncoded = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq" +
+ "Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR" +
+ "TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e" +
+ "UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9" +
+ "AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn" +
+ "sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x" +
+ "nQIDAQAB";
+ byte[] encodedBytes = Base64.getDecoder().decode(pemEncoded);
+
+ final X509EncodedKeySpec spec = new X509EncodedKeySpec(encodedBytes);
+ final KeyFactory kf = KeyFactory.getInstance("RSA");
+ final RSAPublicKey pk = (RSAPublicKey) kf.generatePublic(spec);
+
+ contextInfo.setSignerKey(pk);
+
+ return Optional.of(contextInfo);
+ }
+
+ @Produces
+ JWTAuthContextInfo getContextInfo() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ return getOptionalContextInfo().get();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/jaxrs/MPJWPProviderRegistration.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/jaxrs/MPJWPProviderRegistration.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/jaxrs/MPJWPProviderRegistration.java
new file mode 100644
index 0000000..34f152f
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/jaxrs/MPJWPProviderRegistration.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.jaxrs;
+
+import org.apache.openejb.observer.Observes;
+import org.apache.openejb.server.cxf.rs.event.ExtensionProviderRegistration;
+import org.apache.tomee.microprofile.jwt.MPJWTFilter;
+
+/**
+ * OpenEJB/TomEE hack to register a new provider on the fly
+ * Could be package in tomee only or done in another way
+ *
+ * As soon as Roberto is done with the packaging, we can remove all this and providers are going to be scanned automatically
+ */
+public class MPJWPProviderRegistration {
+
+ public void registerProvider(@Observes final ExtensionProviderRegistration event) {
+ event.getProviders().add(new MPJWTFilter.MPJWTExceptionMapper());
+ event.getProviders().add(new MPJWTSecurityAnnotationsInterceptorsFeature());
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/jaxrs/MPJWTSecurityAnnotationsInterceptor.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/jaxrs/MPJWTSecurityAnnotationsInterceptor.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/jaxrs/MPJWTSecurityAnnotationsInterceptor.java
new file mode 100644
index 0000000..f604e6b
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/jaxrs/MPJWTSecurityAnnotationsInterceptor.java
@@ -0,0 +1,57 @@
+package org.apache.tomee.microprofile.jwt.jaxrs;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.HttpURLConnection;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+public class MPJWTSecurityAnnotationsInterceptor implements ContainerRequestFilter {
+
+ private final javax.ws.rs.container.ResourceInfo resourceInfo;
+ private final ConcurrentMap<Method, Set<String>> rolesAllowed;
+ private final Set<Method> denyAll;
+ private final Set<Method> permitAll;
+
+ public MPJWTSecurityAnnotationsInterceptor(final javax.ws.rs.container.ResourceInfo resourceInfo,
+ final ConcurrentMap<Method, Set<String>> rolesAllowed,
+ final Set<Method> denyAll,
+ final Set<Method> permitAll) {
+ this.resourceInfo = resourceInfo;
+ this.rolesAllowed = rolesAllowed;
+ this.denyAll = denyAll;
+ this.permitAll = permitAll;
+ }
+
+ @Override
+ public void filter(final ContainerRequestContext requestContext) throws IOException {
+ if (permitAll.contains(resourceInfo.getResourceMethod())) {
+ return;
+ }
+
+ if (denyAll.contains(resourceInfo.getResourceMethod())) {
+ forbidden(requestContext);
+ return;
+ }
+
+ final Set<String> roles = rolesAllowed.get(resourceInfo.getResourceMethod());
+ if (roles != null && !roles.isEmpty()) {
+ final SecurityContext securityContext = requestContext.getSecurityContext();
+ for (String role : roles) {
+ if (!securityContext.isUserInRole(role)) {
+ forbidden(requestContext);
+ break;
+ }
+ }
+ }
+
+ }
+
+ private void forbidden(final ContainerRequestContext requestContext) {
+ requestContext.abortWith(Response.status(HttpURLConnection.HTTP_FORBIDDEN).build());
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/jaxrs/MPJWTSecurityAnnotationsInterceptorsFeature.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/jaxrs/MPJWTSecurityAnnotationsInterceptorsFeature.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/jaxrs/MPJWTSecurityAnnotationsInterceptorsFeature.java
new file mode 100644
index 0000000..58b3203
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/jaxrs/MPJWTSecurityAnnotationsInterceptorsFeature.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.jaxrs;
+
+import javax.annotation.security.DenyAll;
+import javax.annotation.security.PermitAll;
+import javax.annotation.security.RolesAllowed;
+import javax.ws.rs.container.DynamicFeature;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.ext.Provider;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+@Provider
+public class MPJWTSecurityAnnotationsInterceptorsFeature implements DynamicFeature {
+
+ private final ConcurrentMap<Method, Set<String>> rolesAllowed = new ConcurrentHashMap<>();
+ private final Set<Method> denyAll = new HashSet<>();
+ private final Set<Method> permitAll = new HashSet<>();
+
+ @Override
+ public void configure(final ResourceInfo resourceInfo, final FeatureContext context) {
+
+ final boolean hasSecurity = processSecurityAnnotations(resourceInfo.getResourceClass(), resourceInfo.getResourceMethod());
+
+ if (hasSecurity) { // no need to add interceptor on the resources that don(t have any security requirements to enforce
+ context.register(new MPJWTSecurityAnnotationsInterceptor(resourceInfo, rolesAllowed, denyAll, permitAll));
+ }
+
+ }
+
+ private boolean processSecurityAnnotations(final Class clazz, final Method method) {
+
+ final List<Class<? extends Annotation>[]> classSecurityAnnotations = hasClassLevelAnnotations(clazz,
+ RolesAllowed.class, PermitAll.class, DenyAll.class);
+
+ final List<Class<? extends Annotation>[]> methodSecurityAnnotations = hasMethodLevelAnnotations(method,
+ RolesAllowed.class, PermitAll.class, DenyAll.class);
+
+ if (classSecurityAnnotations.size() == 0 && methodSecurityAnnotations.size() == 0) {
+ return false; // nothing to do
+ }
+
+ /*
+ * Process annotations at the class level
+ */
+ if (classSecurityAnnotations.size() > 1) {
+ throw new IllegalStateException(clazz.getName() + " has more than one security annotation (RolesAllowed, PermitAll, DenyAll).");
+ }
+
+ if (methodSecurityAnnotations.size() > 1) {
+ throw new IllegalStateException(method.toString() + " has more than one security annotation (RolesAllowed, PermitAll, DenyAll).");
+ }
+
+ if (methodSecurityAnnotations.size() == 0) { // no need to deal with class level annotations if the method has some
+ final RolesAllowed classRolesAllowed = (RolesAllowed) clazz.getAnnotation(RolesAllowed.class);
+ final PermitAll classPermitAll = (PermitAll) clazz.getAnnotation(PermitAll.class);
+ final DenyAll classDenyAll = (DenyAll) clazz.getAnnotation(DenyAll.class);
+
+ if (classRolesAllowed != null) {
+ Set<String> roles = new HashSet<String>();
+ final Set<String> previous = rolesAllowed.putIfAbsent(method, roles);
+ if (previous != null) {
+ roles = previous;
+ }
+ roles.addAll(Arrays.asList(classRolesAllowed.value()));
+ }
+
+ if (classPermitAll != null) {
+ permitAll.add(method);
+ }
+
+ if (classDenyAll != null) {
+ denyAll.add(method);
+ }
+ }
+
+ final RolesAllowed mthdRolesAllowed = method.getAnnotation(RolesAllowed.class);
+ final PermitAll mthdPermitAll = method.getAnnotation(PermitAll.class);
+ final DenyAll mthdDenyAll = method.getAnnotation(DenyAll.class);
+
+ if (mthdRolesAllowed != null) {
+ Set<String> roles = new HashSet<String>();
+ final Set<String> previous = rolesAllowed.putIfAbsent(method, roles);
+ if (previous != null) {
+ roles = previous;
+ }
+ roles.addAll(Arrays.asList(mthdRolesAllowed.value()));
+ }
+
+ if (mthdPermitAll != null) {
+ permitAll.add(method);
+ }
+
+ if (mthdDenyAll != null) {
+ denyAll.add(method);
+ }
+
+ return true;
+ }
+
+ private List<Class<? extends Annotation>[]> hasClassLevelAnnotations(final Class clazz, final Class<? extends Annotation>... annotationsToCheck) {
+ final List<Class<? extends Annotation>[]> list = new ArrayList<>();
+ for (Class<? extends Annotation> annotationToCheck : annotationsToCheck) {
+ if (clazz.isAnnotationPresent(annotationToCheck)) {
+ list.add(annotationsToCheck);
+ }
+ }
+ return list;
+ }
+
+ private List<Class<? extends Annotation>[]> hasMethodLevelAnnotations(final Method method, final Class<? extends Annotation>... annotationsToCheck) {
+ final List<Class<? extends Annotation>[]> list = new ArrayList<>();
+ for (Class<? extends Annotation> annotationToCheck : annotationsToCheck) {
+ if (method.isAnnotationPresent(annotationToCheck)) {
+ list.add(annotationsToCheck);
+ }
+ }
+ return list;
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipal.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipal.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipal.java
new file mode 100644
index 0000000..661fbde
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipal.java
@@ -0,0 +1,360 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.principal;
+
+import org.eclipse.microprofile.jwt.Claims;
+import org.jose4j.jwt.JwtClaims;
+import org.jose4j.jwt.MalformedClaimException;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonValue;
+import javax.security.auth.Subject;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A default implementation of JWTCallerPrincipal using jose4j
+ * Another implementation could use nimbus and another plain JSON-P
+ */
+public class DefaultJWTCallerPrincipal extends JWTCallerPrincipal {
+
+ private static final Logger logger = Logger.getLogger(DefaultJWTCallerPrincipal.class.getName());
+ private final String jwt;
+ private final String type;
+ private final JwtClaims claimsSet;
+
+ /**
+ * Create the DefaultJWTCallerPrincipal from the parsed JWT token and the extracted principal name
+ *
+ * @param jwt - the parsed JWT token representation
+ * @param name - the extracted unqiue name to use as the principal name; from "upn", "preferred_username" or "sub" claim
+ */
+ public DefaultJWTCallerPrincipal(final String jwt, final String type, final JwtClaims claimsSet, final String name) {
+ super(name);
+ this.jwt = jwt;
+ this.type = type;
+ this.claimsSet = claimsSet;
+ fixJoseTypes();
+ }
+
+ @Override
+ public Set<String> getAudience() {
+ final Set<String> audSet = new HashSet<>();
+ try {
+ final List<String> audList = claimsSet.getStringListClaimValue("aud");
+ if (audList != null) {
+ audSet.addAll(audList);
+ }
+
+ } catch (final MalformedClaimException e) {
+ try {
+ final String aud = claimsSet.getStringClaimValue("aud");
+ audSet.add(aud);
+ } catch (final MalformedClaimException e1) {
+ logger.log(Level.FINEST, "Can't retrieve malformed 'aud' claim.", e);
+ }
+ }
+ return audSet.isEmpty() ? null : audSet;
+ }
+
+ @Override
+ public Set<String> getGroups() {
+ final HashSet<String> groups = new HashSet<>();
+ try {
+ final List<String> globalGroups = claimsSet.getStringListClaimValue("groups");
+ if (globalGroups != null) {
+ groups.addAll(globalGroups);
+ }
+
+ } catch (final MalformedClaimException e) {
+ logger.log(Level.FINEST, "Can't retrieve malformed 'groups' claim.", e);
+ }
+ return groups;
+ }
+
+
+ @Override
+ public Set<String> getClaimNames() {
+ return new HashSet<>(claimsSet.getClaimNames());
+ }
+
+ public String getRawToken() {
+ return jwt;
+ }
+
+ @Override
+ public Object getClaim(final String claimName) {
+ Claims claimType = Claims.UNKNOWN;
+ Object claim = null;
+ try {
+ claimType = Claims.valueOf(claimName);
+ } catch (IllegalArgumentException e) {
+ }
+ // Handle the jose4j NumericDate types and
+ switch (claimType) {
+ case exp:
+ case iat:
+ case auth_time:
+ case nbf:
+ case updated_at:
+ try {
+ claim = claimsSet.getClaimValue(claimType.name(), Long.class);
+ if (claim == null) {
+ claim = new Long(0);
+ }
+ } catch (final MalformedClaimException e) {
+ logger.log(Level.FINEST, "Can't retrieve 'updated_at' a malformed claim.", e);
+ }
+ break;
+ case groups:
+ claim = getGroups();
+ break;
+ case aud:
+ claim = getAudience();
+ break;
+ case UNKNOWN:
+ claim = claimsSet.getClaimValue(claimName);
+ break;
+ default:
+ claim = claimsSet.getClaimValue(claimType.name());
+ }
+ return claim;
+ }
+
+ @Override
+ public boolean implies(final Subject subject) {
+ return false;
+ }
+
+ public String toString() {
+ return toString(false);
+ }
+
+ /**
+ * TODO: showAll is ignored and currently assumed true
+ *
+ * @param showAll - should all claims associated with the JWT be displayed or should only those defined in the
+ * JsonWebToken interface be displayed.
+ * @return JWTCallerPrincipal string view
+ */
+ @Override
+ public String toString(boolean showAll) {
+ String toString = "DefaultJWTCallerPrincipal{" +
+ "id='" + getTokenID() + '\'' +
+ ", name='" + getName() + '\'' +
+ ", expiration=" + getExpirationTime() +
+ ", notBefore=" + getClaim(Claims.nbf.name()) +
+ ", issuedAt=" + getIssuedAtTime() +
+ ", issuer='" + getIssuer() + '\'' +
+ ", audience=" + getAudience() +
+ ", subject='" + getSubject() + '\'' +
+ ", type='" + type + '\'' +
+ ", issuedFor='" + getClaim("azp") + '\'' +
+ ", authTime=" + getClaim("auth_time") +
+ ", givenName='" + getClaim("given_name") + '\'' +
+ ", familyName='" + getClaim("family_name") + '\'' +
+ ", middleName='" + getClaim("middle_name") + '\'' +
+ ", nickName='" + getClaim("nickname") + '\'' +
+ ", preferredUsername='" + getClaim("preferred_username") + '\'' +
+ ", email='" + getClaim("email") + '\'' +
+ ", emailVerified=" + getClaim(Claims.email_verified.name()) +
+ ", allowedOrigins=" + getClaim("allowedOrigins") +
+ ", updatedAt=" + getClaim("updated_at") +
+ ", acr='" + getClaim("acr") + '\'';
+
+ final StringBuilder tmp = new StringBuilder(toString);
+ tmp.append(", groups=[");
+ for (String group : getGroups()) {
+ tmp.append(group);
+ tmp.append(',');
+ }
+ tmp.setLength(tmp.length() - 1);
+ tmp.append("]}");
+ return tmp.toString();
+ }
+
+ /**
+ * Convert the types jose4j uses for address, sub_jwk, and jwk
+ */
+ private void fixJoseTypes() {
+ if (claimsSet.hasClaim(Claims.address.name())) {
+ replaceMap(Claims.address.name());
+ }
+ if (claimsSet.hasClaim(Claims.jwk.name())) {
+ replaceMap(Claims.jwk.name());
+ }
+ if (claimsSet.hasClaim(Claims.sub_jwk.name())) {
+ replaceMap(Claims.sub_jwk.name());
+ }
+
+ // Handle custom claims
+ final Set<String> customClaimNames = filterCustomClaimNames(claimsSet.getClaimNames());
+ for (String name : customClaimNames) {
+ final Object claimValue = claimsSet.getClaimValue(name);
+ if (claimValue instanceof List) {
+ replaceList(name);
+
+ } else if (claimValue instanceof Map) {
+ replaceMap(name);
+
+ } else if (claimValue instanceof Number) {
+ replaceNumber(name);
+ }
+ }
+ }
+
+ /**
+ * Determine the custom claims in the set
+ *
+ * @param claimNames - the current set of claim names in this token
+ * @return the possibly empty set of names for non-Claims claims
+ */
+ private Set<String> filterCustomClaimNames(final Collection<String> claimNames) {
+ final HashSet<String> customNames = new HashSet<>(claimNames);
+ for (Claims claim : Claims.values()) {
+ customNames.remove(claim.name());
+ }
+ return customNames;
+ }
+
+ /**
+ * Replace the jose4j Map<String,Object> with a JsonObject
+ *
+ * @param name - claim name
+ */
+ private void replaceMap(final String name) {
+ try {
+ final Map<String, Object> map = claimsSet.getClaimValue(name, Map.class);
+ final JsonObject jsonObject = replaceMap(map);
+ claimsSet.setClaim(name, jsonObject);
+
+ } catch (final MalformedClaimException e) {
+ logger.log(Level.WARNING, "replaceMap failure for: " + name, e);
+ }
+ }
+
+ private JsonObject replaceMap(final Map<String, Object> map) {
+ final JsonObjectBuilder builder = Json.createObjectBuilder();
+
+ for (Map.Entry<String, Object> entry : map.entrySet()) {
+ final Object entryValue = entry.getValue();
+ if (entryValue instanceof Map) {
+ final JsonObject entryJsonObject = replaceMap((Map<String, Object>) entryValue);
+ builder.add(entry.getKey(), entryJsonObject);
+
+ } else if (entryValue instanceof List) {
+ final JsonArray array = (JsonArray) wrapValue(entryValue);
+ builder.add(entry.getKey(), array);
+
+ } else if (entryValue instanceof Long || entryValue instanceof Integer) {
+ final long lvalue = ((Number) entryValue).longValue();
+ builder.add(entry.getKey(), lvalue);
+
+ } else if (entryValue instanceof Double || entryValue instanceof Float) {
+ final double value = ((Number) entryValue).doubleValue();
+ builder.add(entry.getKey(), value);
+
+ } else if (entryValue instanceof Boolean) {
+ final boolean flag = ((Boolean) entryValue).booleanValue();
+ builder.add(entry.getKey(), flag);
+
+ } else if (entryValue instanceof String) {
+ builder.add(entry.getKey(), entryValue.toString());
+ }
+ }
+ return builder.build();
+ }
+
+ private JsonValue wrapValue(final Object value) {
+ JsonValue jsonValue = null;
+ if (value instanceof Number) {
+ final Number number = (Number) value;
+ if ((number instanceof Long) || (number instanceof Integer)) {
+ jsonValue = Json.createObjectBuilder()
+ .add("tmp", number.longValue())
+ .build()
+ .getJsonNumber("tmp");
+
+ } else {
+ jsonValue = Json.createObjectBuilder()
+ .add("tmp", number.doubleValue())
+ .build()
+ .getJsonNumber("tmp");
+ }
+
+ } else if (value instanceof Boolean) {
+ final Boolean flag = (Boolean) value;
+ jsonValue = flag ? JsonValue.TRUE : JsonValue.FALSE;
+
+ } else if (value instanceof List) {
+ final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
+ final List list = (List) value;
+ for (Object element : list) {
+ if (element instanceof String) {
+ arrayBuilder.add(element.toString());
+
+ } else {
+ JsonValue jvalue = wrapValue(element);
+ arrayBuilder.add(jvalue);
+ }
+
+ }
+ jsonValue = arrayBuilder.build();
+
+ }
+ return jsonValue;
+ }
+
+
+ /**
+ * Replace the jose4j List<?> with a JsonArray
+ *
+ * @param name - claim name
+ */
+ private void replaceList(final String name) {
+ try {
+ final List list = claimsSet.getClaimValue(name, List.class);
+ final JsonArray array = (JsonArray) wrapValue(list);
+ claimsSet.setClaim(name, array);
+
+ } catch (final MalformedClaimException e) {
+ logger.log(Level.WARNING, "replaceList failure for: " + name, e);
+ }
+ }
+
+ private void replaceNumber(final String name) {
+ try {
+ final Number number = claimsSet.getClaimValue(name, Number.class);
+ final JsonNumber jsonNumber = (JsonNumber) wrapValue(number);
+ claimsSet.setClaim(name, jsonNumber);
+
+ } catch (final MalformedClaimException e) {
+ logger.log(Level.WARNING, "replaceNumber failure for: " + name, e);
+ }
+ }
+
+}
\ No newline at end of file
[5/8] tomee git commit: Make a simple test case to wire up everything
and start adding a simple UI on top
Posted by jl...@apache.org.
Make a simple test case to wire up everything and start adding a simple UI on top
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/b4a44e40
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/b4a44e40
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/b4a44e40
Branch: refs/heads/fb_tomee8
Commit: b4a44e401a916985caec4b8ea309fe9ab0cbf7c5
Parents: def443a
Author: Jean-Louis Monteiro <je...@gmail.com>
Authored: Thu Apr 19 23:28:51 2018 +0200
Committer: Jean-Louis Monteiro <je...@gmail.com>
Committed: Thu Apr 19 23:28:51 2018 +0200
----------------------------------------------------------------------
examples/pom.xml | 1 +
examples/rest-mp-jwt/README.md | 0
examples/rest-mp-jwt/pom.xml | 278 +++++++++++++++++++
.../main/java/org/superbiz/moviefun/Movie.java | 102 +++++++
.../java/org/superbiz/moviefun/MoviesBean.java | 91 ++++++
.../moviefun/rest/ApplicationConfig.java | 28 ++
.../org/superbiz/moviefun/rest/LoadRest.java | 42 +++
.../rest/MoviesMPJWTConfigurationProvider.java | 63 +++++
.../org/superbiz/moviefun/rest/MoviesRest.java | 113 ++++++++
.../java/org/superbiz/rest/GreetingService.java | 41 +++
.../src/main/resources/META-INF/persistence.xml | 31 +++
examples/rest-mp-jwt/src/main/tomee/tomee.xml | 27 ++
.../rest-mp-jwt/src/main/webapp/WEB-INF/web.xml | 46 +++
.../rest-mp-jwt/src/main/webapp/app/app.less | 62 +++++
.../rest-mp-jwt/src/main/webapp/app/config.js | 45 +++
.../src/main/webapp/app/js/application.js | 193 +++++++++++++
.../rest-mp-jwt/src/main/webapp/app/js/i18n.js | 66 +++++
.../rest-mp-jwt/src/main/webapp/app/js/id.js | 43 +++
.../rest-mp-jwt/src/main/webapp/app/js/log.js | 40 +++
.../src/main/webapp/app/js/model/movie.js | 48 ++++
.../src/main/webapp/app/js/model/movies.js | 35 +++
.../rest-mp-jwt/src/main/webapp/app/js/start.js | 29 ++
.../src/main/webapp/app/js/templates.js | 69 +++++
...pplication-table-paginator-button.handlebars | 1 +
.../templates/application-table-row.handlebars | 8 +
.../app/js/templates/application.handlebars | 50 ++++
.../app/js/templates/container.handlebars | 10 +
.../app/js/templates/load-data-link.handlebars | 1 +
.../webapp/app/js/templates/movie.handlebars | 56 ++++
.../app/js/view/application-table-paginator.js | 77 +++++
.../webapp/app/js/view/application-table-row.js | 63 +++++
.../src/main/webapp/app/js/view/application.js | 135 +++++++++
.../src/main/webapp/app/js/view/container.js | 62 +++++
.../src/main/webapp/app/js/view/movie.js | 75 +++++
examples/rest-mp-jwt/src/main/webapp/index.jsp | 36 +++
.../java/org/superbiz/moviefun/MoviesTest.java | 88 ++++++
.../java/org/superbiz/moviefun/TokenUtils.java | 257 +++++++++++++++++
.../org/superbiz/rest/GreetingServiceTest.java | 61 ++++
.../resources/META-INF/application-client.xml | 1 +
.../rest-mp-jwt/src/test/resources/Token1.json | 20 ++
.../rest-mp-jwt/src/test/resources/Token2.json | 12 +
.../src/test/resources/arquillian.xml | 32 +++
.../src/test/resources/privateKey.pem | 28 ++
.../src/test/resources/publicKey.pem | 9 +
.../microprofile/jwt/cdi/MPJWTCDIExtension.java | 45 +--
.../jwt/config/JWTAuthContextInfoProvider.java | 61 ----
.../jwt/JWTAuthContextInfoProvider.java | 63 +++++
.../jwt/AppDeploymentExtension.java | 3 +-
48 files changed, 2646 insertions(+), 101 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/pom.xml
----------------------------------------------------------------------
diff --git a/examples/pom.xml b/examples/pom.xml
index fab0d95..18d4971 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -119,6 +119,7 @@ BROKEN, see TOMEE-2140
<module>rest-applicationcomposer</module>
<module>rest-cdi</module>
<module>rest-jaas</module>
+ <module>rest-mp-jwt</module>
<module>rest-on-ejb</module>
<module>rest-example</module>
<module>rest-example-with-application</module>
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/README.md
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/README.md b/examples/rest-mp-jwt/README.md
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/pom.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/pom.xml b/examples/rest-mp-jwt/pom.xml
new file mode 100644
index 0000000..f2656b3
--- /dev/null
+++ b/examples/rest-mp-jwt/pom.xml
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<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.superbiz</groupId>
+ <artifactId>rest-mp-jwt</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <packaging>war</packaging>
+ <name>OpenEJB :: Examples :: REST MP-JWT</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <tomee.version>8.0.0-SNAPSHOT</tomee.version>
+ <version.shrinkwrap.resolver>2.0.0</version.shrinkwrap.resolver>
+ <mp-jwt.version>1.1-SNAPSHOT</mp-jwt.version>
+ </properties>
+
+ <build>
+ <defaultGoal>install</defaultGoal>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.18.1</version>
+ <configuration>
+ <reuseForks>false</reuseForks>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>3.1.0</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.5.1</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.tomee.maven</groupId>
+ <artifactId>tomee-maven-plugin</artifactId>
+ <version>${tomee.version}</version>
+ <configuration>
+ <tomeeClassifier>microprofile</tomeeClassifier>
+ <args>-Xmx512m -XX:PermSize=256m</args>
+ <config>${project.basedir}/src/main/tomee/</config>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencyManagement>
+ <dependencies>
+ <!-- Override dependency resolver with test version. This must go *BEFORE*
+ the Arquillian BOM. -->
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-bom</artifactId>
+ <version>${version.shrinkwrap.resolver}</version>
+ <scope>import</scope>
+ <type>pom</type>
+ </dependency>
+ <!-- Now pull in our server-based unit testing framework -->
+ <dependency>
+ <groupId>org.jboss.arquillian</groupId>
+ <artifactId>arquillian-bom</artifactId>
+ <version>1.0.3.Final</version>
+ <scope>import</scope>
+ <type>pom</type>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <repositories>
+ <repository>
+ <id>apache-m2-snapshot</id>
+ <name>Apache Snapshot Repository</name>
+ <url>https://repository.apache.org/content/groups/snapshots</url>
+ </repository>
+ </repositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>javaee-api</artifactId>
+ <version>8.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.microprofile.jwt</groupId>
+ <artifactId>microprofile-jwt-auth-api</artifactId>
+ <version>${mp-jwt.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.nimbusds</groupId>
+ <artifactId>nimbus-jose-jwt</artifactId>
+ <version>4.23</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+
+ <!--
+ The <scope>test</scope> guarantees that non of your runtime
+ code is dependent on any OpenEJB classes.
+ -->
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>openejb-cxf-rs</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>openejb-core</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.junit</groupId>
+ <artifactId>arquillian-junit-container</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-depchain</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>ziplock</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>backbonejs</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>bootstrap</artifactId>
+ <version>3.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>handlebars</artifactId>
+ <version>1.2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>jquery</artifactId>
+ <version>2.1.0-1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>json2</artifactId>
+ <version>20110223</version>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>less</artifactId>
+ <version>1.6.0-1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>requirejs</artifactId>
+ <version>2.1.10</version>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>requirejs-text</artifactId>
+ <version>2.0.10</version>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>arquillian-tomee-embedded</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>arquillian-tomee-embedded</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>tomee-embedded</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>mp-jwt</artifactId>
+ <version>${tomee.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+ <profile>
+ <id>arquillian-tomee-remote</id>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>arquillian-tomee-remote</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>apache-tomee</artifactId>
+ <version>${tomee.version}</version>
+ <type>zip</type>
+ <classifier>microprofile</classifier>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+ </profiles>
+
+ <!--
+ This section allows you to configure where to publish libraries for sharing.
+ It is not required and may be deleted. For more information see:
+ http://maven.apache.org/plugins/maven-deploy-plugin/
+ -->
+ <distributionManagement>
+ <repository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/repo/</url>
+ </repository>
+ <snapshotRepository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/snapshot-repo/</url>
+ </snapshotRepository>
+ </distributionManagement>
+</project>
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/Movie.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/Movie.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/Movie.java
new file mode 100644
index 0000000..4e067bb
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/Movie.java
@@ -0,0 +1,102 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.moviefun;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@Entity
+@XmlRootElement(name = "movie")
+public class Movie {
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long id;
+
+ private String director;
+ private String title;
+ private int year;
+ private String genre;
+ private int rating;
+
+ public Movie() {
+ }
+
+ public Movie(String title, String director, String genre, int rating, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ this.genre = genre;
+ this.rating = rating;
+ }
+
+ public Movie(String director, String title, int year) {
+ this.director = director;
+ this.title = title;
+ this.year = year;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+
+ public String getGenre() {
+ return genre;
+ }
+
+ public void setGenre(String genre) {
+ this.genre = genre;
+ }
+
+ public int getRating() {
+ return rating;
+ }
+
+ public void setRating(int rating) {
+ this.rating = rating;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/MoviesBean.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/MoviesBean.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/MoviesBean.java
new file mode 100644
index 0000000..2580c9f
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/MoviesBean.java
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.moviefun;
+
+import javax.ejb.Stateless;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import javax.persistence.metamodel.EntityType;
+import java.util.List;
+
+@Stateless
+public class MoviesBean {
+
+ @PersistenceContext(unitName = "movie-unit")
+ private EntityManager entityManager;
+
+ public Movie find(Long id) {
+ return entityManager.find(Movie.class, id);
+ }
+
+ public void addMovie(Movie movie) {
+ entityManager.persist(movie);
+ }
+
+ public void editMovie(Movie movie) {
+ entityManager.merge(movie);
+ }
+
+ public void deleteMovie(long id) {
+ Movie movie = entityManager.find(Movie.class, id);
+ entityManager.remove(movie);
+ }
+
+ public List<Movie> getMovies(Integer firstResult, Integer maxResults, String field, String searchTerm) {
+ CriteriaBuilder qb = entityManager.getCriteriaBuilder();
+ CriteriaQuery<Movie> cq = qb.createQuery(Movie.class);
+ Root<Movie> root = cq.from(Movie.class);
+ EntityType<Movie> type = entityManager.getMetamodel().entity(Movie.class);
+ if (field != null && searchTerm != null && !"".equals(field.trim()) && !"".equals(searchTerm.trim())) {
+ Path<String> path = root.get(type.getDeclaredSingularAttribute(field.trim(), String.class));
+ Predicate condition = qb.like(path, "%" + searchTerm.trim() + "%");
+ cq.where(condition);
+ }
+ TypedQuery<Movie> q = entityManager.createQuery(cq);
+ if (maxResults != null) {
+ q.setMaxResults(maxResults);
+ }
+ if (firstResult != null) {
+ q.setFirstResult(firstResult);
+ }
+ return q.getResultList();
+ }
+
+ public int count(String field, String searchTerm) {
+ CriteriaBuilder qb = entityManager.getCriteriaBuilder();
+ CriteriaQuery<Long> cq = qb.createQuery(Long.class);
+ Root<Movie> root = cq.from(Movie.class);
+ EntityType<Movie> type = entityManager.getMetamodel().entity(Movie.class);
+ cq.select(qb.count(root));
+ if (field != null && searchTerm != null && !"".equals(field.trim()) && !"".equals(searchTerm.trim())) {
+ Path<String> path = root.get(type.getDeclaredSingularAttribute(field.trim(), String.class));
+ Predicate condition = qb.like(path, "%" + searchTerm.trim() + "%");
+ cq.where(condition);
+ }
+ return entityManager.createQuery(cq).getSingleResult().intValue();
+ }
+
+ public void clean() {
+ entityManager.createQuery("delete from Movie").executeUpdate();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/ApplicationConfig.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/ApplicationConfig.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/ApplicationConfig.java
new file mode 100644
index 0000000..5a7bd4d
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/ApplicationConfig.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.moviefun.rest;
+
+import org.eclipse.microprofile.auth.LoginConfig;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+@ApplicationPath("/rest")
+@LoginConfig(authMethod = "MP-JWT")
+public class ApplicationConfig extends Application {
+ // let the server discover the endpoints
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/LoadRest.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/LoadRest.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/LoadRest.java
new file mode 100644
index 0000000..6969221
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/LoadRest.java
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.moviefun.rest;
+
+import org.superbiz.moviefun.Movie;
+import org.superbiz.moviefun.MoviesBean;
+
+import javax.ejb.EJB;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+@Path("load")
+public class LoadRest {
+ @EJB
+ private MoviesBean moviesBean;
+
+ @POST
+ public void load() {
+ moviesBean.addMovie(new Movie("Wedding Crashers", "David Dobkin", "Comedy", 7, 2005));
+ moviesBean.addMovie(new Movie("Starsky & Hutch", "Todd Phillips", "Action", 6, 2004));
+ moviesBean.addMovie(new Movie("Shanghai Knights", "David Dobkin", "Action", 6, 2003));
+ moviesBean.addMovie(new Movie("I-Spy", "Betty Thomas", "Adventure", 5, 2002));
+ moviesBean.addMovie(new Movie("The Royal Tenenbaums", "Wes Anderson", "Comedy", 8, 2001));
+ moviesBean.addMovie(new Movie("Zoolander", "Ben Stiller", "Comedy", 6, 2001));
+ moviesBean.addMovie(new Movie("Shanghai Noon", "Tom Dey", "Comedy", 7, 2000));
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesMPJWTConfigurationProvider.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesMPJWTConfigurationProvider.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesMPJWTConfigurationProvider.java
new file mode 100644
index 0000000..3bea531
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesMPJWTConfigurationProvider.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.moviefun.rest;
+
+import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Produces;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+import java.util.Optional;
+
+@Dependent
+public class MoviesMPJWTConfigurationProvider {
+
+ @Produces
+ Optional<JWTAuthContextInfo> getOptionalContextInfo() throws NoSuchAlgorithmException, InvalidKeySpecException {
+ JWTAuthContextInfo contextInfo = new JWTAuthContextInfo();
+
+ // todo use MP Config to load the configuration
+ contextInfo.setIssuedBy("https://server.example.com");
+
+ final String pemEncoded = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq" +
+ "Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR" +
+ "TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e" +
+ "UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9" +
+ "AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn" +
+ "sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x" +
+ "nQIDAQAB";
+ byte[] encodedBytes = Base64.getDecoder().decode(pemEncoded);
+
+ final X509EncodedKeySpec spec = new X509EncodedKeySpec(encodedBytes);
+ final KeyFactory kf = KeyFactory.getInstance("RSA");
+ final RSAPublicKey pk = (RSAPublicKey) kf.generatePublic(spec);
+
+ contextInfo.setSignerKey(pk);
+
+ return Optional.of(contextInfo);
+ }
+
+ @Produces
+ JWTAuthContextInfo getContextInfo() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ return getOptionalContextInfo().get();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesRest.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesRest.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesRest.java
new file mode 100644
index 0000000..7020864
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesRest.java
@@ -0,0 +1,113 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.moviefun.rest;
+
+import org.eclipse.microprofile.jwt.Claim;
+import org.eclipse.microprofile.jwt.ClaimValue;
+import org.eclipse.microprofile.jwt.JsonWebToken;
+import org.superbiz.moviefun.Movie;
+import org.superbiz.moviefun.MoviesBean;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ejb.EJB;
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+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.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.SecurityContext;
+import java.util.List;
+
+@Path("movies")
+@Produces({"application/json"})
+public class MoviesRest {
+
+ @EJB
+ private MoviesBean service;
+
+ @Inject
+ @Claim("raw_token")
+ private ClaimValue<String> rawToken;
+
+ @Inject
+ @Claim("iss")
+ private ClaimValue<String> issuer;
+
+ @Inject
+ @Claim("jti")
+ private ClaimValue<String> jti;
+
+ @Inject
+ private JsonWebToken jwtPrincipal;
+
+ @Context
+ private SecurityContext securityContext;
+
+ @GET
+ @Path("{id}")
+ public Movie find(@PathParam("id") Long id) {
+ return service.find(id);
+ }
+
+ @GET
+ public List<Movie> getMovies(@QueryParam("first") Integer first, @QueryParam("max") Integer max,
+ @QueryParam("field") String field, @QueryParam("searchTerm") String searchTerm) {
+ return service.getMovies(first, max, field, searchTerm);
+ }
+
+ @POST
+ @Consumes("application/json")
+ @RolesAllowed("create")
+ public Movie addMovie(Movie movie) {
+ service.addMovie(movie);
+ return movie;
+ }
+
+ @PUT
+ @Path("{id}")
+ @Consumes("application/json")
+ @RolesAllowed("update")
+ public Movie editMovie(
+ @PathParam("id") final long id,
+ Movie movie
+ ) {
+ service.editMovie(movie);
+ return movie;
+ }
+
+ @DELETE
+ @Path("{id}")
+ @RolesAllowed("delete")
+ public void deleteMovie(@PathParam("id") long id) {
+ service.deleteMovie(id);
+ }
+
+ @GET
+ @Path("count")
+ @Produces(MediaType.TEXT_PLAIN)
+ public int count(@QueryParam("field") String field, @QueryParam("searchTerm") String searchTerm) {
+ return service.count(field, searchTerm);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/rest/GreetingService.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/rest/GreetingService.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/rest/GreetingService.java
new file mode 100644
index 0000000..eb4434e
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/rest/GreetingService.java
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.rest;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.util.Locale;
+
+@Path("/greeting")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+public class GreetingService {
+
+ @GET
+ public String message() {
+ return "Hi Microprofile JWT!";
+ }
+
+ @POST
+ public String lowerCase(final String message) {
+ return message.toLowerCase(Locale.ENGLISH);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/resources/META-INF/persistence.xml b/examples/rest-mp-jwt/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 0000000..ec38aaa
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
+ <persistence-unit name="movie-unit">
+ <jta-data-source>movieDatabase</jta-data-source>
+ <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+ <class>org.superbiz.moviefun.Movie</class>
+
+ <properties>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ </properties>
+ </persistence-unit>
+</persistence>
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/tomee/tomee.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/tomee/tomee.xml b/examples/rest-mp-jwt/src/main/tomee/tomee.xml
new file mode 100644
index 0000000..f25d5f8
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/tomee/tomee.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<tomee>
+ <Resource id="HSQLDB Database" type="DataSource">
+ JdbcDriver org.hsqldb.jdbcDriver
+ JdbcUrl jdbc:hsqldb:file:target/db/moviefun
+ UserName sa
+ Password
+ </Resource>
+</tomee>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/WEB-INF/web.xml b/examples/rest-mp-jwt/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..328247d
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
+ <welcome-file-list>
+ <welcome-file>index.jsp</welcome-file>
+ </welcome-file-list>
+
+ <!-- The trick is to put all your static files under the same directory and map the "default" servlet to it -->
+ <servlet-mapping>
+ <servlet-name>default</servlet-name>
+ <url-pattern>/app/*</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>default</servlet-name>
+ <url-pattern>/webjars/*</url-pattern>
+ </servlet-mapping>
+
+ <!-- Any other request will point to the "index.jsp" page. This way Backbone knows how to manage page transitions
+ at the client side in case the user starts the application from a permalink. -->
+ <servlet>
+ <servlet-name>application</servlet-name>
+ <jsp-file>/index.jsp</jsp-file>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>application</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>
+
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/app.less
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/app.less b/examples/rest-mp-jwt/src/main/webapp/app/app.less
new file mode 100644
index 0000000..61fd5e2
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/app.less
@@ -0,0 +1,62 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+body {
+ @content-margin-top: 80px;
+
+ .ux-movie-window {
+ .modal-dialog {
+ padding-top: 90px;
+ padding-bottom: 0px;
+ }
+ }
+
+ .ux-landing {
+ margin-top: @content-margin-top;
+ }
+
+ .ux-setup {
+ margin-top: @content-margin-top;
+ }
+
+ .ux-application {
+ margin-top: @content-margin-top;
+
+ .pagination {
+ margin-top: 0px;
+ margin-bottom: 0px;
+ }
+
+ th:last-child {
+ width: 5px;
+ }
+
+ .ux-add-btn {
+ position: absolute;
+ bottom: 20px;
+ right: 30px;
+ }
+
+ a.ux-delete-row:hover, a.ux-edit-row:hover {
+ cursor: hand;
+ }
+
+ .panel-body>.input-group {
+ margin-bottom: 15px;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/config.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/config.js b/examples/rest-mp-jwt/src/main/webapp/app/config.js
new file mode 100644
index 0000000..bbdc5e1
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/config.js
@@ -0,0 +1,45 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var APP_CONFIG = {
+ baseUrl: window.ux.ROOT_URL,
+ paths: {
+ 'text': 'webjars/requirejs-text/2.0.10/text',
+ 'lib/less': 'webjars/less/1.6.0/less.min',
+ 'lib/jquery': 'webjars/jquery/2.1.0/jquery.min',
+ 'lib/bootstrap': 'webjars/bootstrap/3.1.0/js/bootstrap.min',
+ 'lib/handlebars': 'webjars/handlebars/1.2.1/handlebars.min',
+ 'lib/underscore': 'webjars/underscorejs/1.4.3/underscore-min',
+ 'lib/json2': 'webjars/json2/20110223/json2.min',
+ 'lib/backbone': 'webjars/backbonejs/1.0.0/backbone'
+ },
+ shim: {
+ 'lib/bootstrap': {
+ deps: ['lib/jquery']
+ },
+ 'lib/underscore': {
+ exports: '_'
+ },
+ 'lib/backbone': {
+ deps: ['lib/jquery', 'lib/json2', 'lib/underscore']
+ },
+ 'app/js/templates': {
+ deps: ['lib/underscore', 'app/js/i18n']
+ }
+ }
+};
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/application.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/application.js b/examples/rest-mp-jwt/src/main/webapp/app/js/application.js
new file mode 100644
index 0000000..9ec4cab
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/application.js
@@ -0,0 +1,193 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ var deps = [
+ 'app/js/view/container',
+ 'app/js/view/application',
+ 'app/js/view/application-table-paginator',
+ 'app/js/view/movie',
+ 'lib/underscore',
+ 'app/js/model/movies',
+ 'app/js/model/movie',
+ 'app/js/i18n',
+ 'lib/less', 'lib/backbone', 'lib/jquery', 'lib/bootstrap'
+ ];
+ define(deps, function (containerView, applicationView, paginator, MovieView, underscore, moviesList, MovieModel) {
+ var max = 5;
+ var appState = {
+ page: null,
+ fieldName: null,
+ fieldValue: null
+ };
+ containerView.render();
+
+ $.ajaxSetup({ cache: false });
+
+ function loadPage(pageNumber, fieldName, fieldValue) {
+ var data = {
+ max: max,
+ first: ((pageNumber - 1) * max)
+ };
+ if (fieldName && fieldValue) {
+ data.field = fieldName;
+ data.searchTerm = fieldValue;
+ }
+ applicationView.setFilter(fieldName, fieldValue);
+ moviesList.fetch({
+ data: data,
+ success: function (result) {
+ applicationView.addRows(result.models);
+
+ $.ajax({
+ url: window.ux.ROOT_URL + 'rest/movies/count/',
+ method: 'GET',
+ dataType: 'json',
+ data: {
+ field: appState.fieldName,
+ searchTerm: appState.fieldValue
+ },
+ success: function (total) {
+ var count = Math.ceil(total / max);
+ paginator.setCount(count);
+ applicationView.setPaginator(count);
+ }
+ });
+ }
+ });
+ }
+
+ function start() {
+ //Starting the backbone router.
+ var Router = Backbone.Router.extend({
+ routes: {
+ '': 'showApplication',
+ 'application': 'showApplication',
+ 'application/:page': 'showApplication',
+ 'application/:page/:field/:value': 'showApplication'
+ },
+
+ showApplication: function (page, fieldName, fieldValue) {
+ var me = this;
+ appState.page = page;
+ appState.fieldName = fieldName;
+ appState.fieldValue = fieldValue;
+ containerView.showView(applicationView);
+ if (!page || !underscore.isNumber(Number(page))) {
+ me.showApplication(1);
+ } else {
+ loadPage(Number(page), fieldName, fieldValue);
+ if (fieldName) {
+ me.navigate('application/' + page + '/' + fieldName + '/' + fieldValue, {
+ trigger: false
+ });
+ } else {
+ me.navigate('application/' + page, {
+ trigger: false
+ });
+ }
+ }
+ }
+ });
+ var router = new Router();
+
+ applicationView.on('load-sample', function () {
+ $.ajax({
+ url: window.ux.ROOT_URL + 'rest/load/',
+ method: 'POST',
+ dataType: 'json',
+ data: {},
+ success: function (data) {
+ router.showApplication();
+ }
+ });
+ });
+
+ applicationView.on('delete', function (data) {
+ data.model.destroy({
+ success: function () {
+ router.showApplication(appState.page, appState.fieldName, appState.fieldValue);
+ }
+ });
+ });
+
+ function showMovieWindow(model) {
+ var view = new MovieView({
+ model: model
+ });
+ view.render();
+ view.on('save-model', function (data) {
+ data.model.save({}, {
+ success: function () {
+ view.remove();
+ loadPage(appState.page, appState.fieldName, appState.fieldValue);
+ }
+ });
+ });
+ $('body').append(view.$el);
+ view.$el.modal({});
+ }
+
+ applicationView.on('add', function () {
+ showMovieWindow(new MovieModel({}));
+ });
+
+ applicationView.on('edit', function (data) {
+ showMovieWindow(data.model);
+ });
+
+ applicationView.on('filter', function (data) {
+ router.navigate('application/1/' + data.filterType + '/' + data.filterValue, {
+ trigger: true
+ });
+ });
+
+ applicationView.on('clear-filter', function (data) {
+ router.navigate('application/1', {
+ trigger: true
+ });
+ });
+
+ paginator.on('go-to-page', function (data) {
+ var page = data.number;
+ if (page === 'last') {
+ page = paginator.getCount();
+ }
+ router.showApplication(page, appState.fieldName, appState.fieldValue);
+ });
+
+ //Starting the backbone history.
+ Backbone.history.start({
+ pushState: true,
+ root: window.ux.ROOT_URL // This value is set by <c:url>
+ });
+
+ return {
+ getRouter: function () {
+ return router;
+ }
+ };
+ }
+
+ return {
+ start: start
+ };
+ });
+}());
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/i18n.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/i18n.js b/examples/rest-mp-jwt/src/main/webapp/app/js/i18n.js
new file mode 100644
index 0000000..2603dec
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/i18n.js
@@ -0,0 +1,66 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ "use strict";
+ */
+
+define(['lib/underscore', 'lib/handlebars', 'app/js/log'], function (underscore) {
+ 'use strict';
+
+ var missing = Handlebars.compile('[!{{key}}!]');
+ var messages = {
+ 'application.name': 'Moviefun',
+ 'load.dada': 'Click here to load sample data',
+ 'movies': 'Movies',
+ 'title': 'Title',
+ 'director': 'Director',
+ 'genre': 'Genre',
+ 'rating': 'Rating',
+ 'year': 'Year',
+ 'add.movie': 'Add movie',
+ 'movie': 'Movie',
+ 'close': 'Close',
+ 'save': 'Save',
+
+ 'dummy': ''
+ };
+
+ underscore.each(underscore.keys(messages), function (key) {
+ var template = Handlebars.compile(messages[key]);
+ messages[key] = template;
+ });
+
+ var get = function (key, values) {
+ var template = messages[key];
+ var cfg = values;
+ if (!template) {
+ template = missing;
+ cfg = {
+ key: key
+ };
+ window.console.error('Missing i18n message.', key);
+ }
+ return template(cfg);
+ };
+
+ Handlebars.registerHelper('i18n', function (key) {
+ return get(key);
+ });
+
+ return {
+ get: get
+ };
+});
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/id.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/id.js b/examples/rest-mp-jwt/src/main/webapp/app/js/id.js
new file mode 100644
index 0000000..fc4c56a
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/id.js
@@ -0,0 +1,43 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ "use strict";
+ */
+
+define(['lib/underscore', 'lib/handlebars'], function (underscore) {
+ 'use strict';
+
+ var value = underscore.uniqueId('moviefun_');
+
+ var current = function () {
+ return value;
+ };
+ var next = function () {
+ value = underscore.uniqueId('moviefun_');
+ return value;
+ };
+ Handlebars.registerHelper('id_current', function (key) {
+ return current();
+ });
+ Handlebars.registerHelper('id_next', function (key) {
+ return next();
+ });
+
+ return {
+ current: current,
+ next: next
+ };
+});
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/log.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/log.js b/examples/rest-mp-jwt/src/main/webapp/app/js/log.js
new file mode 100644
index 0000000..6e79b98
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/log.js
@@ -0,0 +1,40 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+define([], function () {
+ 'use strict';
+
+ var noOp = function () {
+ return ''; // no-op
+ };
+
+ if (!window.console) {
+ window.console = {};
+ }
+
+ function createIfNull(functionName) {
+ if (!window.console[functionName]) {
+ window.console[functionName] = noOp;
+ }
+ }
+
+ createIfNull('error');
+ createIfNull('warn');
+ createIfNull('log');
+ createIfNull('info');
+});
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/model/movie.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/model/movie.js b/examples/rest-mp-jwt/src/main/webapp/app/js/model/movie.js
new file mode 100644
index 0000000..36be222
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/model/movie.js
@@ -0,0 +1,48 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ var deps = ['lib/backbone'];
+ define(deps, function () {
+ var isString = function (obj) {
+ return Object.prototype.toString.call(obj) === '[object String]';
+ };
+ return Backbone.Model.extend({
+ urlRoot: window.ux.ROOT_URL + 'rest/movies',
+ idAttribute: 'id',
+ toJSON: function () {
+ if (!!this.attributes.rating && isString(this.attributes.rating)) {
+ this.attributes.rating = parseInt(this.attributes.rating, 10);
+ }
+ if (!!this.attributes.year && isString(this.attributes.year)) {
+ this.attributes.year = parseInt(this.attributes.year, 10);
+ }
+ if (!!this.attributes.id && isString(this.attributes.id)) {
+ this.attributes.id = parseInt(this.attributes.id, 10);
+ }
+ return this.attributes;
+ },
+ defaults: {
+ rating: 5,
+ year: new Date().getFullYear()
+ }
+ });
+ });
+}());
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/model/movies.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/model/movies.js b/examples/rest-mp-jwt/src/main/webapp/app/js/model/movies.js
new file mode 100644
index 0000000..828d2f8
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/model/movies.js
@@ -0,0 +1,35 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ var deps = ['app/js/model/movie', 'lib/backbone'];
+ define(deps, function (Movie) {
+ var Cls = Backbone.Collection.extend({
+ model: Movie,
+ url: window.ux.ROOT_URL + 'rest/movies',
+ parse: function (response) {
+ return response;
+ }
+ });
+ return new Cls();
+ });
+}());
+
+
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/start.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/start.js b/examples/rest-mp-jwt/src/main/webapp/app/js/start.js
new file mode 100644
index 0000000..33f7fbd
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/start.js
@@ -0,0 +1,29 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+require.config(APP_CONFIG);
+
+requirejs(['app/js/application'], function (app) {
+ 'use strict';
+
+ $(window.document).ready(function () {
+ // all the action is in app
+ app.start();
+ });
+});
+
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates.js b/examples/rest-mp-jwt/src/main/webapp/app/js/templates.js
new file mode 100644
index 0000000..e3f3300
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates.js
@@ -0,0 +1,69 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ var files = [
+ 'container',
+ 'application',
+ 'application-table-row',
+ 'application-table-paginator-button',
+ 'load-data-link',
+ 'movie'
+ ];
+
+ function loop(values, callback) {
+ var index;
+ for (index = 0; index < values.length; index += 1) {
+ callback(values[index], index);
+ }
+ }
+
+ // Preparing the "requirements" paths.
+ var requirements = [];
+ loop(files, function (file) {
+ requirements.push('text!app/js/templates/' + file + '.handlebars');
+ });
+
+ define(requirements, function () {
+ var templates = {};
+
+ var myArgs = arguments;
+ loop(files, function (file, i) {
+ templates[file] = Handlebars.compile(myArgs[i]);
+ });
+
+ return {
+ getValue: function (templateName, cfg) {
+ var template = templates[templateName];
+ if (!template) {
+ throw 'Template not registered. "' + templateName + '"';
+ }
+ var result;
+ if (cfg) {
+ result = template(cfg);
+ } else {
+ result = template({});
+ }
+ return result;
+ }
+ };
+ });
+}());
+
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-paginator-button.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-paginator-button.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-paginator-button.handlebars
new file mode 100644
index 0000000..0031aba
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-paginator-button.handlebars
@@ -0,0 +1 @@
+<li><a href="{{pageNumber}}">{{pageText}}</a></li>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-row.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-row.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-row.handlebars
new file mode 100644
index 0000000..dc9bf7c
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-row.handlebars
@@ -0,0 +1,8 @@
+<td><a href="edit" class="ux-edit-row">{{title}}</a></td>
+<td>{{director}}</td>
+<td>{{genre}}</td>
+<td>{{rating}}</td>
+<td>{{year}}</td>
+<td>
+ <a href="delete" class="ux-delete-row"><span class="glyphicon glyphicon-trash"></span></a>
+</td>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application.handlebars
new file mode 100644
index 0000000..f15d1a9
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application.handlebars
@@ -0,0 +1,50 @@
+<div class="row">
+ <div class="col-md-12">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 class="panel-title">{{i18n "movies"}}</h3>
+ </div>
+ <div class="panel-body">
+ <div class="input-group">
+ <div class="input-group-btn">
+ <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
+ <span class="ux-selected-filter">{{i18n "title"}}</span> <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu" role="menu">
+ <li><a href="title" class="ux-filter">{{i18n "title"}}</a></li>
+ <li><a href="director" class="ux-filter">{{i18n "director"}}</a></li>
+ <li><a href="genre" class="ux-filter">{{i18n "genre"}}</a></li>
+ <li><a href="rating" class="ux-filter">{{i18n "rating"}}</a></li>
+ <li><a href="year" class="ux-filter">{{i18n "year"}}</a></li>
+ </ul>
+ </div><!-- /btn-group -->
+ <input type="text" class="form-control ux-filter-field">
+ <span class="input-group-btn">
+ <button class="btn btn-primary ux-clear-filter-action" type="button">
+ <span class="glyphicon glyphicon-remove-circle"></span>
+ </button>
+ <button class="btn btn-primary ux-filter-action" type="button">
+ <span class="glyphicon glyphicon-search"></span>
+ </button>
+ </span>
+ </div>
+ <table class="table table-bordered table-striped table-hover">
+ <thead>
+ <tr>
+ <th>{{i18n "title"}}</th>
+ <th>{{i18n "director"}}</th>
+ <th>{{i18n "genre"}}</th>
+ <th>{{i18n "rating"}}</th>
+ <th>{{i18n "year"}}</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody></tbody>
+ </table>
+ <button type="button" class="btn btn-primary ux-add-btn">{{i18n "add.movie"}}</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates/container.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/container.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/container.handlebars
new file mode 100644
index 0000000..dba60dd
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/container.handlebars
@@ -0,0 +1,10 @@
+<div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="container">
+ <div class="navbar-header">
+ <a class="navbar-brand" href="#">{{i18n "application.name"}}</a>
+ </div>
+ </div>
+</div>
+<div class="container">
+ <div class="ux-contentarea"></div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates/load-data-link.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/load-data-link.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/load-data-link.handlebars
new file mode 100644
index 0000000..1785578
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/load-data-link.handlebars
@@ -0,0 +1 @@
+<a href="load-data">{{i18n "load.dada"}}</a>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates/movie.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/movie.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/movie.handlebars
new file mode 100644
index 0000000..97c511c
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/movie.handlebars
@@ -0,0 +1,56 @@
+<div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+ <h4 class="modal-title">{{i18n "movie"}}</h4>
+ </div>
+ <div class="modal-body">
+ <form class="form-horizontal" role="form">
+ <div class="form-group">
+ <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "title"}}</label>
+
+ <div class="col-lg-10">
+ <input class="form-control ux-title" id="{{id_current}}" placeholder="{{i18n 'title'}}"
+ type="text" value="{{title}}">
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "director"}}</label>
+
+ <div class="col-lg-10">
+ <input class="form-control ux-director" id="{{id_current}}"
+ type="text" placeholder="{{i18n 'director'}}" value="{{director}}">
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "genre"}}</label>
+
+ <div class="col-lg-10">
+ <input class="form-control ux-genre" id="{{id_current}}" placeholder="{{i18n 'genre'}}"
+ type="text" value="{{genre}}">
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "rating"}}</label>
+
+ <div class="col-lg-10">
+ <input class="form-control ux-rating" id="{{id_current}}"
+ type="number" min="0" max="10" placeholder="{{i18n 'rating'}}" value="{{rating}}">
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "year"}}</label>
+
+ <div class="col-lg-10">
+ <input class="form-control ux-year" id="{{id_current}}" placeholder="{{i18n 'year'}}"
+ type="number" min="1900" max="{{currentYear}}" value="{{year}}">
+ </div>
+ </div>
+ </form>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default ux-close" data-dismiss="modal">{{i18n "close"}}</button>
+ <button type="button" class="btn btn-primary ux-save" data-dismiss="modal">{{i18n "save"}}</button>
+ </div>
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-paginator.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-paginator.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-paginator.js
new file mode 100644
index 0000000..c5d2422
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-paginator.js
@@ -0,0 +1,77 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ var deps = ['app/js/templates', 'lib/backbone'];
+ define(deps, function (templates) {
+
+ var View = Backbone.View.extend({
+ tagName: 'ul',
+ className: 'pagination',
+
+ count: 0,
+
+ events: {
+ 'click a': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ var myLink = $(evt.target);
+ var href = myLink.attr('href');
+ me.trigger('go-to-page', {
+ number: href
+ });
+ }
+ },
+
+ render: function () {
+ var me = this;
+ me.$el.empty();
+ me.$el.append(templates.getValue('application-table-paginator-button', {
+ pageNumber: '1',
+ pageText: '<<'
+ }));
+ var i;
+ for (i = 1; i < me.count + 1; i += 1) {
+ me.$el.append(templates.getValue('application-table-paginator-button', {
+ pageNumber: i,
+ pageText: i
+ }));
+ }
+ me.$el.append(templates.getValue('application-table-paginator-button', {
+ pageNumber: 'last',
+ pageText: '>>'
+ }));
+ return this;
+ },
+
+ setCount: function (count) {
+ var me = this;
+ me.count = count;
+ me.render();
+ },
+
+ getCount: function () {
+ var me = this;
+ return me.count;
+ }
+ });
+ return new View().render();
+ });
+}());
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-row.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-row.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-row.js
new file mode 100644
index 0000000..771a062
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-row.js
@@ -0,0 +1,63 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ var deps = ['app/js/templates', 'lib/backbone'];
+ define(deps, function (templates) {
+
+ var View = Backbone.View.extend({
+ tagName: 'tr',
+ events: {
+ 'click .ux-delete-row': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ me.trigger('delete', {
+ model: me.model
+ });
+ me.remove();
+ },
+ 'click .ux-edit-row': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ me.trigger('edit', {
+ model: me.model
+ });
+ }
+ },
+
+ render: function () {
+ var me = this;
+ if (!this.options.isRendered) {
+ me.$el.empty();
+ me.$el.append(templates.getValue('application-table-row', {
+ title: me.model.get('title'),
+ director: me.model.get('director'),
+ genre: me.model.get('genre'),
+ rating: me.model.get('rating'),
+ year: me.model.get('year')
+ }));
+ me.options.isRendered = true;
+ }
+ return this;
+ }
+ });
+ return View;
+ });
+}());
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/view/application.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/application.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application.js
new file mode 100644
index 0000000..7dae6b3
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application.js
@@ -0,0 +1,135 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ var deps = ['app/js/templates', 'app/js/view/application-table-row', 'app/js/view/application-table-paginator',
+ 'lib/underscore', 'app/js/i18n', 'lib/backbone'];
+ define(deps, function (templates, TableRowView, paginator, underscore, i18n) {
+
+ var View = Backbone.View.extend({
+ tagName: 'div',
+ className: 'ux-application',
+
+ loadDataLink: $(templates.getValue('load-data-link', {})),
+
+ filterOption: 'title',
+
+ events: {
+ 'click .ux-filter': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ var selected = $(me.$el.find('.ux-selected-filter').get(0));
+ var myLink = $(evt.target);
+ me.filterOption = myLink.attr('href');
+ selected.html(i18n.get(me.filterOption, {}));
+ },
+ 'click .ux-filter-action': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ var filterValue = $(me.$el.find('.ux-filter-field').get(0)).val();
+ filterValue = $.trim(filterValue);
+ if (filterValue !== '') {
+ me.trigger('filter', {
+ filterType: me.filterOption,
+ filterValue: filterValue
+ });
+ }
+ },
+ 'click .ux-clear-filter-action': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ me.trigger('clear-filter', {});
+ },
+ 'click .ux-application': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ me.trigger('navigate', {
+ path: 'application'
+ });
+ },
+ 'click .ux-add-btn': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ me.trigger('add', {});
+ }
+ },
+
+ setFilter: function (fieldName, fieldValue) {
+ var field = fieldName;
+ var value = fieldValue;
+ if (!fieldName || $.trim(fieldName) === '') {
+ field = 'title';
+ value = '';
+ }
+ var me = this;
+ me.filterOption = field;
+ $(me.$el.find('.ux-selected-filter').get(0)).html(i18n.get(me.filterOption, {}));
+ $(me.$el.find('.ux-filter-field').get(0)).val(value);
+ },
+
+ render: function () {
+ var me = this;
+ if (!this.options.isRendered) {
+ me.$el.empty();
+ me.$el.append(templates.getValue('application', {}));
+ me.loadDataLink.on('click', function (evt) {
+ evt.preventDefault();
+ me.trigger('load-sample', {});
+ });
+ me.options.isRendered = true;
+ }
+ return this;
+ },
+
+ addRows: function (rows) {
+ var me = this;
+ var tbody = $(me.$el.find('tbody').get(0));
+ tbody.empty();
+ paginator.$el.detach();
+ me.loadDataLink.detach();
+ underscore.each(rows, function (model) {
+ var row = new TableRowView({
+ model: model
+ });
+ row.on('delete', function (data) {
+ me.trigger('delete', data);
+ });
+ row.on('edit', function (data) {
+ me.trigger('edit', data);
+ });
+ tbody.append(row.render().$el);
+ });
+ },
+
+ setPaginator: function (count) {
+ var me = this;
+ paginator.$el.detach();
+ me.loadDataLink.detach();
+ var table = $(me.$el.find('.table').get(0));
+ if (count) {
+ table.after(paginator.$el);
+ } else {
+ table.after(me.loadDataLink);
+ }
+ }
+ });
+ return new View();
+ });
+}());
[6/8] tomee git commit: POM clean up and use final MP_JWT 1.0 until
the next release is out
Posted by jl...@apache.org.
POM clean up and use final MP_JWT 1.0 until the next release is out
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/ebf29ec9
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/ebf29ec9
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/ebf29ec9
Branch: refs/heads/fb_tomee8
Commit: ebf29ec904d4fdf6e8efb385da86d940474b5dd7
Parents: b4a44e4
Author: Jean-Louis Monteiro <je...@gmail.com>
Authored: Fri Apr 20 12:52:32 2018 +0200
Committer: Jean-Louis Monteiro <je...@gmail.com>
Committed: Fri Apr 20 12:52:32 2018 +0200
----------------------------------------------------------------------
examples/rest-mp-jwt/pom.xml | 3 ++-
mp-jwt/pom.xml | 4 ----
pom.xml | 3 +++
tck/microprofile-tck/jwt/pom.xml | 9 ++-------
4 files changed, 7 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/ebf29ec9/examples/rest-mp-jwt/pom.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/pom.xml b/examples/rest-mp-jwt/pom.xml
index f2656b3..f100601 100644
--- a/examples/rest-mp-jwt/pom.xml
+++ b/examples/rest-mp-jwt/pom.xml
@@ -30,11 +30,12 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<tomee.version>8.0.0-SNAPSHOT</tomee.version>
<version.shrinkwrap.resolver>2.0.0</version.shrinkwrap.resolver>
- <mp-jwt.version>1.1-SNAPSHOT</mp-jwt.version>
+ <mp-jwt.version>1.0</mp-jwt.version>
</properties>
<build>
<defaultGoal>install</defaultGoal>
+ <finalName>moviefun</finalName>
<plugins>
<plugin>
http://git-wip-us.apache.org/repos/asf/tomee/blob/ebf29ec9/mp-jwt/pom.xml
----------------------------------------------------------------------
diff --git a/mp-jwt/pom.xml b/mp-jwt/pom.xml
index a6cae6a..b1b86f6 100644
--- a/mp-jwt/pom.xml
+++ b/mp-jwt/pom.xml
@@ -27,10 +27,6 @@
<packaging>jar</packaging>
<name>OpenEJB :: Microprofile JWT</name>
- <properties>
- <mp-jwt.version>1.1-SNAPSHOT</mp-jwt.version>
- </properties>
-
<dependencies>
<dependency>
<groupId>org.apache.tomee</groupId>
http://git-wip-us.apache.org/repos/asf/tomee/blob/ebf29ec9/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 82b50dd..ac36c1c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -191,6 +191,9 @@
<!-- arquillian related -->
<version.arquillian.bom>1.1.13.Final</version.arquillian.bom>
<version.shrinkwrap.resolver.bom>2.1.0</version.shrinkwrap.resolver.bom>
+
+ <mp-jwt.version>1.0</mp-jwt.version>
+ <mp-jwt-tck.version>${mp-jwt.version}</mp-jwt-tck.version>
</properties>
<build>
http://git-wip-us.apache.org/repos/asf/tomee/blob/ebf29ec9/tck/microprofile-tck/jwt/pom.xml
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/pom.xml b/tck/microprofile-tck/jwt/pom.xml
index 923c386..088e128 100644
--- a/tck/microprofile-tck/jwt/pom.xml
+++ b/tck/microprofile-tck/jwt/pom.xml
@@ -26,11 +26,6 @@
<artifactId>microprofile-jwt-tck</artifactId>
<name>OpenEJB :: TCK :: MicroProfile JWT TCK</name>
-
- <properties>
- <tck.version>1.1-SNAPSHOT</tck.version>
- </properties>
-
<dependencies>
<dependency>
@@ -66,14 +61,14 @@
<dependency>
<groupId>org.eclipse.microprofile.jwt</groupId>
<artifactId>microprofile-jwt-auth-tck</artifactId>
- <version>${tck.version}</version>
+ <version>${mp-jwt-tck.version}</version>
</dependency>
<!-- This is the actual MP-JWT TCK test classes -->
<dependency>
<groupId>org.eclipse.microprofile.jwt</groupId>
<artifactId>microprofile-jwt-auth-tck</artifactId>
- <version>${tck.version}</version>
+ <version>${mp-jwt-tck.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
[8/8] tomee git commit: Merge remote-tracking branch
'apache/fb_tomee8' into TOMEE-2185_mp-jwt
Posted by jl...@apache.org.
Merge remote-tracking branch 'apache/fb_tomee8' into TOMEE-2185_mp-jwt
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/6d591bbb
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/6d591bbb
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/6d591bbb
Branch: refs/heads/fb_tomee8
Commit: 6d591bbbdb4b36b3b9a58fe1fab199997e6725b3
Parents: 3e579aa f3c5c2d
Author: Jean-Louis Monteiro <je...@gmail.com>
Authored: Thu Apr 26 17:10:00 2018 +0200
Committer: Jean-Louis Monteiro <je...@gmail.com>
Committed: Thu Apr 26 17:10:00 2018 +0200
----------------------------------------------------------------------
.../arquillian-tomee-webprofile-tests/pom.xml | 6 ++
.../openejb/arquillian/tests/ear/CodecBean.java | 32 +++++++++
.../arquillian/tests/ear/CodecServlet.java | 44 ++++++++++++
.../tests/ear/EarCommonsCodecTest.java | 73 ++++++++++++++++++++
pom.xml | 4 +-
5 files changed, 157 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/6d591bbb/pom.xml
----------------------------------------------------------------------
[2/8] tomee git commit: Missing files from previous commit
Posted by jl...@apache.org.
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipalFactory.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipalFactory.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipalFactory.java
new file mode 100644
index 0000000..feb2008
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipalFactory.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.principal;
+
+import org.apache.tomee.microprofile.jwt.ParseException;
+import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo;
+import org.eclipse.microprofile.jwt.Claims;
+import org.jose4j.jwa.AlgorithmConstraints;
+import org.jose4j.jws.AlgorithmIdentifiers;
+import org.jose4j.jwt.JwtClaims;
+import org.jose4j.jwt.MalformedClaimException;
+import org.jose4j.jwt.NumericDate;
+import org.jose4j.jwt.consumer.InvalidJwtException;
+import org.jose4j.jwt.consumer.JwtConsumer;
+import org.jose4j.jwt.consumer.JwtConsumerBuilder;
+import org.jose4j.jwt.consumer.JwtContext;
+
+/**
+ * A default implementation of the abstract JWTCallerPrincipalFactory that uses the Keycloak token parsing classes.
+ */
+public class DefaultJWTCallerPrincipalFactory extends JWTCallerPrincipalFactory {
+
+ /**
+ * Tries to load the JWTAuthContextInfo from CDI if the class level authContextInfo has not been set.
+ */
+ public DefaultJWTCallerPrincipalFactory() {
+ }
+
+ @Override
+ public JWTCallerPrincipal parse(final String token, final JWTAuthContextInfo authContextInfo) throws ParseException {
+ JWTCallerPrincipal principal;
+
+ try {
+ final JwtConsumerBuilder builder = new JwtConsumerBuilder()
+ .setRequireExpirationTime()
+ .setRequireSubject()
+ .setSkipDefaultAudienceValidation()
+ .setExpectedIssuer(authContextInfo.getIssuedBy())
+ .setVerificationKey(authContextInfo.getSignerKey())
+ .setJwsAlgorithmConstraints(
+ new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.WHITELIST,
+ AlgorithmIdentifiers.RSA_USING_SHA256));
+
+ if (authContextInfo.getExpGracePeriodSecs() > 0) {
+ builder.setAllowedClockSkewInSeconds(authContextInfo.getExpGracePeriodSecs());
+
+ } else {
+ builder.setEvaluationTime(NumericDate.fromSeconds(0));
+ }
+
+ final JwtConsumer jwtConsumer = builder.build();
+ final JwtContext jwtContext = jwtConsumer.process(token);
+ final String type = jwtContext.getJoseObjects().get(0).getHeader("typ");
+ // Validate the JWT and process it to the Claims
+ jwtConsumer.processContext(jwtContext);
+ JwtClaims claimsSet = jwtContext.getJwtClaims();
+
+ // We have to determine the unique name to use as the principal name. It comes from upn, preferred_username, sub in that order
+ String principalName = claimsSet.getClaimValue("upn", String.class);
+ if (principalName == null) {
+ principalName = claimsSet.getClaimValue("preferred_username", String.class);
+ if (principalName == null) {
+ principalName = claimsSet.getSubject();
+ }
+ }
+ claimsSet.setClaim(Claims.raw_token.name(), token);
+ principal = new DefaultJWTCallerPrincipal(token, type, claimsSet, principalName);
+
+ } catch (final InvalidJwtException e) {
+ throw new ParseException("Failed to verify token", e);
+
+ } catch (final MalformedClaimException e) {
+ throw new ParseException("Failed to verify token claims", e);
+ }
+
+ return principal;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/JWTCallerPrincipal.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/JWTCallerPrincipal.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/JWTCallerPrincipal.java
new file mode 100644
index 0000000..d8e3c4c
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/JWTCallerPrincipal.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.principal;
+
+
+import org.eclipse.microprofile.jwt.JsonWebToken;
+
+import java.util.Optional;
+
+/**
+ * An abstract CallerPrincipal implementation that provides access to the JWT claims that are required by
+ * the microprofile token.
+ */
+public abstract class JWTCallerPrincipal implements JsonWebToken {
+
+ private String name;
+
+ /**
+ * Create a JWTCallerPrincipal with the caller's name
+ *
+ * @param name - caller's name
+ */
+ public JWTCallerPrincipal(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Generate a human readable version of the caller principal and associated JWT.
+ *
+ * @param showAll - should all claims associated with the JWT be displayed or should only those defined in the
+ * JsonWebToken interface be displayed.
+ * @return human readable presentation of the caller principal and associated JWT.
+ */
+ public abstract String toString(final boolean showAll);
+
+ public <T> Optional<T> claim(final String claimName) {
+ final T claim = (T) getClaim(claimName);
+ return Optional.ofNullable(claim);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/JWTCallerPrincipalFactory.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/JWTCallerPrincipalFactory.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/JWTCallerPrincipalFactory.java
new file mode 100644
index 0000000..e7ebcd6
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/JWTCallerPrincipalFactory.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomee.microprofile.jwt.principal;
+
+import org.apache.tomee.microprofile.jwt.ParseException;
+import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo;
+
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ServiceLoader;
+
+/**
+ * The factory class that provides the token string to JWTCallerPrincipal parsing for a given implementation.
+ */
+public abstract class JWTCallerPrincipalFactory {
+
+ private static JWTCallerPrincipalFactory instance;
+
+ /**
+ * Obtain the JWTCallerPrincipalFactory that has been set or by using the ServiceLoader pattern.
+ *
+ * @return the factory instance
+ * @see #setInstance(JWTCallerPrincipalFactory)
+ */
+ public static JWTCallerPrincipalFactory instance() {
+ if (instance == null) {
+ synchronized (JWTCallerPrincipalFactory.class) {
+ if (instance != null) {
+ return instance;
+ }
+
+ ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ @Override
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ if (cl == null) {
+ cl = JWTCallerPrincipalFactory.class.getClassLoader();
+ }
+
+ JWTCallerPrincipalFactory newInstance = loadSpi(cl);
+
+ if (newInstance == null && cl != JWTCallerPrincipalFactory.class.getClassLoader()) {
+ cl = JWTCallerPrincipalFactory.class.getClassLoader();
+ newInstance = loadSpi(cl);
+ }
+ if (newInstance == null) {
+ throw new IllegalStateException("No JWTCallerPrincipalFactory implementation found!");
+ }
+
+ instance = newInstance;
+ }
+ }
+
+ return instance;
+ }
+
+ /**
+ * Look for a JWTCallerPrincipalFactory service implementation using the ServiceLoader.
+ *
+ * @param cl - the ClassLoader to pass into the {@link ServiceLoader#load(Class, ClassLoader)} method.
+ * @return the JWTCallerPrincipalFactory if found, null otherwise
+ */
+ private static JWTCallerPrincipalFactory loadSpi(ClassLoader cl) {
+ if (cl == null) {
+ return null;
+ }
+
+ // start from the root CL and go back down to the TCCL
+ JWTCallerPrincipalFactory instance = loadSpi(cl.getParent());
+
+ if (instance == null) {
+ ServiceLoader<JWTCallerPrincipalFactory> sl = ServiceLoader.load(JWTCallerPrincipalFactory.class, cl);
+ URL u = cl.getResource("/META-INF/services/org.apache.tomee.microprofile.jwt.JWTCallerPrincipalFactory");
+ System.out.printf("JWTCallerPrincipalFactory, cl=%s, u=%s, sl=%s\n", cl, u, sl);
+ try {
+ for (JWTCallerPrincipalFactory spi : sl) {
+ if (instance != null) {
+ throw new IllegalStateException(
+ "Multiple JWTCallerPrincipalFactory implementations found: "
+ + spi.getClass().getName() + " and "
+ + instance.getClass().getName());
+ } else {
+ System.out.printf("sl=%s, loaded=%s\n", sl, spi);
+ instance = spi;
+ }
+ }
+
+ } catch (final Throwable e) {
+ System.err.printf("Warning: %s\n", e.getMessage());
+ }
+ }
+ return instance;
+ }
+
+ /**
+ * Set the instance. It is used by OSGi environment where service loader pattern is not supported.
+ *
+ * @param resolver the instance to use.
+ */
+ public static void setInstance(final JWTCallerPrincipalFactory resolver) {
+ instance = resolver;
+ }
+
+ /**
+ * Parse the given bearer token string into a JWTCallerPrincipal instance.
+ *
+ * @param token - the bearer token provided for authorization
+ * @return A JWTCallerPrincipal representation for the token.
+ * @throws ParseException on parse or verification failure.
+ */
+ public abstract JWTCallerPrincipal parse(final String token, final JWTAuthContextInfo authContextInfo) throws ParseException;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/resources/META-INF/org.apache.openejb.extension
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/resources/META-INF/org.apache.openejb.extension b/mp-jwt/src/main/resources/META-INF/org.apache.openejb.extension
new file mode 100644
index 0000000..9734019
--- /dev/null
+++ b/mp-jwt/src/main/resources/META-INF/org.apache.openejb.extension
@@ -0,0 +1 @@
+org.apache.tomee.microprofile.jwt.jaxrs.MPJWPProviderRegistration
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/mp-jwt/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
new file mode 100644
index 0000000..d5eea47
--- /dev/null
+++ b/mp-jwt/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -0,0 +1 @@
+org.apache.tomee.microprofile.jwt.cdi.MPJWTCDIExtension
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer b/mp-jwt/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer
new file mode 100644
index 0000000..100e625
--- /dev/null
+++ b/mp-jwt/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer
@@ -0,0 +1 @@
+org.apache.tomee.microprofile.jwt.MPJWTInitializer
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/mp-jwt/src/main/resources/META-INF/services/org.apache.tomee.microprofile.jwt.principal.JWTCallerPrincipalFactory
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/resources/META-INF/services/org.apache.tomee.microprofile.jwt.principal.JWTCallerPrincipalFactory b/mp-jwt/src/main/resources/META-INF/services/org.apache.tomee.microprofile.jwt.principal.JWTCallerPrincipalFactory
new file mode 100644
index 0000000..21c9831
--- /dev/null
+++ b/mp-jwt/src/main/resources/META-INF/services/org.apache.tomee.microprofile.jwt.principal.JWTCallerPrincipalFactory
@@ -0,0 +1 @@
+org.apache.tomee.microprofile.jwt.principal.DefaultJWTCallerPrincipalFactory
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/tck/microprofile-tck/jwt/pom.xml
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/pom.xml b/tck/microprofile-tck/jwt/pom.xml
new file mode 100644
index 0000000..923c386
--- /dev/null
+++ b/tck/microprofile-tck/jwt/pom.xml
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<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">
+ <parent>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>microprofile-tck</artifactId>
+ <version>8.0.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>microprofile-jwt-tck</artifactId>
+ <name>OpenEJB :: TCK :: MicroProfile JWT TCK</name>
+
+
+ <properties>
+ <tck.version>1.1-SNAPSHOT</tck.version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mp-jwt</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <version>${slf4j.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>tomee-catalina</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- distro -->
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apache-tomee</artifactId>
+ <version>${project.version}</version>
+ <type>zip</type>
+ <classifier>microprofile</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- This is the MP-JWT TCK base extension and utility classes -->
+ <dependency>
+ <groupId>org.eclipse.microprofile.jwt</groupId>
+ <artifactId>microprofile-jwt-auth-tck</artifactId>
+ <version>${tck.version}</version>
+ </dependency>
+
+ <!-- This is the actual MP-JWT TCK test classes -->
+ <dependency>
+ <groupId>org.eclipse.microprofile.jwt</groupId>
+ <artifactId>microprofile-jwt-auth-tck</artifactId>
+ <version>${tck.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <version>6.9.9</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>arquillian-tomee-remote</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.testng</groupId>
+ <artifactId>arquillian-testng-core</artifactId>
+ <version>${version.arquillian}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-api-maven</artifactId>
+ <version>2.2.2</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-impl-maven</artifactId>
+ <version>2.2.2</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-spi</artifactId>
+ <version>2.2.2</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-rs-client</artifactId>
+ <version>${cxf.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.10</version>
+ <executions>
+ <execution>
+ <id>copy-tck-test-suite-file</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.eclipse.microprofile.jwt</groupId>
+ <artifactId>microprofile-jwt-auth-tck</artifactId>
+ <type>test-jar</type>
+ <overWrite>true</overWrite>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.17</version>
+ <configuration>
+ <suiteXmlFiles>
+ <!-- TCK does not deliver the xml file for the moment -->
+ <suiteXmlFile>${project.build.directory}/test-classes/dev.xml</suiteXmlFile>
+ </suiteXmlFiles>
+ <systemProperties>
+ <!--<property>-->
+ <!--<name>validation.provider</name>-->
+ <!--<value>${validation.provider}</value>-->
+ <!--</property>-->
+ </systemProperties>
+ <parallel>methods</parallel>
+ <threadCount>4</threadCount>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ <version>2.17</version>
+ <executions>
+ <execution>
+ <id>generate-test-report</id>
+ <phase>test</phase>
+ <goals>
+ <goal>report-only</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <outputDirectory>${project.build.directory}/surefire-reports</outputDirectory>
+ <outputName>test-report</outputName>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java b/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java
new file mode 100644
index 0000000..cf4e837
--- /dev/null
+++ b/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java
@@ -0,0 +1,76 @@
+package org.apache.tomee.microprofile.jwt;
+
+import com.nimbusds.jose.JWSSigner;
+import org.apache.openejb.loader.JarLocation;
+import org.eclipse.microprofile.jwt.tck.TCKConstants;
+import org.eclipse.microprofile.jwt.tck.util.TokenUtils;
+import org.jboss.arquillian.container.spi.client.deployment.DeploymentDescription;
+import org.jboss.arquillian.container.test.impl.client.deployment.AnnotationDeploymentScenarioGenerator;
+import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor;
+import org.jboss.arquillian.container.test.spi.client.deployment.DeploymentScenarioGenerator;
+import org.jboss.arquillian.core.spi.LoadableExtension;
+import org.jboss.arquillian.test.spi.TestClass;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.Node;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Logger;
+
+public class AppDeploymentExtension implements LoadableExtension {
+ @Override
+ public void register(final ExtensionBuilder extensionBuilder) {
+ extensionBuilder.service(DeploymentScenarioGenerator.class, SimpleDeploymentScenarioGenerator.class);
+ extensionBuilder.service(ApplicationArchiveProcessor.class, MPJWTTCKArchiveProcess.class);
+ }
+
+ public static class SimpleDeploymentScenarioGenerator implements DeploymentScenarioGenerator {
+
+ private final DeploymentScenarioGenerator standard = new AnnotationDeploymentScenarioGenerator();
+ private final DeploymentDescription emptyTestWebApp;
+
+ public SimpleDeploymentScenarioGenerator() {
+ emptyTestWebApp = new DeploymentDescription("mp-jwt-tck.war",
+ ShrinkWrap
+ .create(WebArchive.class, "mp-jwt-tck.war")
+ .addAsLibrary(JarLocation.jarLocation(TokenUtils.class))
+ .addAsLibrary(JarLocation.jarLocation(JWSSigner.class))
+ .addAsLibrary(JarLocation.jarLocation(TCKConstants.class).getAbsolutePath().replace("-tests.jar", "-test-sources.jar"))
+ .add(EmptyAsset.INSTANCE, "WEB-INF/beans.xml"));
+ }
+
+
+ @Override
+ public List<DeploymentDescription> generate(final TestClass testClass) {
+ final List<DeploymentDescription> stdDeploymentDescriptions = standard.generate(testClass);
+
+ if (stdDeploymentDescriptions != null && !stdDeploymentDescriptions.isEmpty()) {
+ return stdDeploymentDescriptions;
+ }
+
+ return Collections.singletonList(emptyTestWebApp);
+ }
+ }
+
+ /**
+ * An ApplicationArchiveProcessor for the MP-JWT TCK if needed
+ * With the current implementation we don't need to do anything
+ */
+ public static class MPJWTTCKArchiveProcess implements ApplicationArchiveProcessor {
+ private static Logger log = Logger.getLogger(MPJWTTCKArchiveProcess.class.getName());
+
+ @Override
+ public void process(final Archive<?> appArchive, final TestClass testClass) {
+ if (!(appArchive instanceof WebArchive)) {
+ return;
+ }
+ WebArchive war = WebArchive.class.cast(appArchive);
+
+ log.info("Augmented war: \n"+war.toString(true));
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/tck/microprofile-tck/jwt/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension b/tck/microprofile-tck/jwt/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
new file mode 100644
index 0000000..98a4867
--- /dev/null
+++ b/tck/microprofile-tck/jwt/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
@@ -0,0 +1 @@
+org.apache.tomee.microprofile.jwt.AppDeploymentExtension
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/tck/microprofile-tck/jwt/src/test/resources/arquillian.xml
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/src/test/resources/arquillian.xml b/tck/microprofile-tck/jwt/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..8e7a66b
--- /dev/null
+++ b/tck/microprofile-tck/jwt/src/test/resources/arquillian.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<arquillian
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://jboss.org/schema/arquillian
+ http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
+
+ <container qualifier="tomee" default="true">
+ <configuration>
+ <property name="catalina_opts">-Xmx512m -XX:MaxPermSize=512m</property>
+ <property name="httpPort">-1</property>
+ <property name="stopPort">-1</property>
+ <property name="ajpPort">-1</property>
+ <property name="classifier">microprofile</property>
+ <property name="debug">false</property>
+ <property name="dir">target/tomee-tck</property>
+ <property name="appWorkingDir">target/tck-workdir</property>
+ <property name="simpleLog">true</property>
+ <property name="properties"></property>
+ </configuration>
+ </container>
+</arquillian>
http://git-wip-us.apache.org/repos/asf/tomee/blob/def443a4/tck/microprofile-tck/jwt/src/test/resources/dev.xml
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/src/test/resources/dev.xml b/tck/microprofile-tck/jwt/src/test/resources/dev.xml
new file mode 100644
index 0000000..00741d1
--- /dev/null
+++ b/tck/microprofile-tck/jwt/src/test/resources/dev.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
+<suite name="microprofile-jwt-auth-FullTCK" verbose="1" preserve-order="true" configfailurepolicy="continue" >
+
+ <!-- The required base JAX-RS and CDI based tests that all MP-JWT implementations
+ must pass.
+ -->
+
+ <test name="base-tests" verbose="10">
+ <groups>
+ <define name="base-groups">
+ <include name="arquillian" description="Arquillian internal"/>
+ <include name="utils" description="Utility tests"/>
+ <include name="jwt" description="Base JsonWebToken tests"/>
+ <include name="jaxrs" description="JAX-RS invocation tests"/>
+ <include name="cdi" description="Base CDI injection of ClaimValues"/>
+ <include name="cdi-json" description="CDI injection of JSON-P values"/>
+ <include name="cdi-provider" description="CDI injection of javax.inject.Provider values"/>
+ </define>
+ <define name="excludes">
+ <include name="debug" description="Internal debugging tests" />
+ </define>
+ <run>
+ <include name="base-groups" />
+ <exclude name="excludes" />
+ </run>
+ </groups>
+ <classes>
+ <class name="org.eclipse.microprofile.jwt.tck.parsing.TokenValidationTest" />
+ <class name="org.eclipse.microprofile.jwt.tck.util.TokenUtilsTest" />
+ <class name="org.eclipse.microprofile.jwt.tck.parsing.TestTokenClaimTypesTest" />
+ <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.UnsecuredPingTest" />
+ <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.RequiredClaimsTest" />
+ <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.PrimitiveInjectionTest" />
+ <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.ClaimValueInjectionTest" />
+ <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.JsonValueInjectionTest" />
+ <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.ProviderInjectionTest" />
+ <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.InvalidTokenTest" />
+ <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.RolesAllowedTest" />
+ <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.RolesAllowedTest" />
+ <!--
+ -->
+ </classes>
+ </test>
+
+ <test name="extended-tests" verbose="10">
+ <groups>
+ <define name="extended-groups">
+ <include name="arquillian" description="Arquillian internal"/>
+ <include name="ejb-optional" description="EJB container integration tests"/>
+ <include name="jacc-optional" description="JACC API integration tests"/>
+ <include name="servlet-optional" description="Servlet container integration tests"/>
+ <include name="ee-security-optional" description="Java EE security feature tests"/>
+ </define>
+ <define name="excludes">
+ <include name="debug" description="Internal debugging tests" />
+ </define>
+ <run>
+ <include name="extended-groups" />
+ <exclude name="excludes" />
+ </run>
+ </groups>
+ <classes>
+ <class name="org.eclipse.microprofile.jwt.tck.container.ejb.EjbTest" >
+ <methods>
+ <!-- Excluded cause we never really enforce ACC context for EJB Calls in TomEE -->
+ <exclude name="getSubjectClass"/>
+ </methods>
+ </class>
+
+ <class name="org.eclipse.microprofile.jwt.tck.container.servlet.ServletTest" />
+ <class name="org.eclipse.microprofile.jwt.tck.container.jacc.SubjectTest" />
+ <!--
+ -->
+ </classes>
+ </test>
+</suite>
[7/8] tomee git commit: No need for the UI part here
Posted by jl...@apache.org.
No need for the UI part here
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/3e579aad
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/3e579aad
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/3e579aad
Branch: refs/heads/fb_tomee8
Commit: 3e579aad22e21cf239604e00bcb6a3b22646f6c8
Parents: ebf29ec
Author: Jean-Louis Monteiro <je...@gmail.com>
Authored: Mon Apr 23 15:01:15 2018 +0200
Committer: Jean-Louis Monteiro <je...@gmail.com>
Committed: Mon Apr 23 15:01:15 2018 +0200
----------------------------------------------------------------------
.../rest-mp-jwt/src/main/webapp/WEB-INF/web.xml | 46 -----
.../rest-mp-jwt/src/main/webapp/app/app.less | 62 ------
.../rest-mp-jwt/src/main/webapp/app/config.js | 45 -----
.../src/main/webapp/app/js/application.js | 193 -------------------
.../rest-mp-jwt/src/main/webapp/app/js/i18n.js | 66 -------
.../rest-mp-jwt/src/main/webapp/app/js/id.js | 43 -----
.../rest-mp-jwt/src/main/webapp/app/js/log.js | 40 ----
.../src/main/webapp/app/js/model/movie.js | 48 -----
.../src/main/webapp/app/js/model/movies.js | 35 ----
.../rest-mp-jwt/src/main/webapp/app/js/start.js | 29 ---
.../src/main/webapp/app/js/templates.js | 69 -------
...pplication-table-paginator-button.handlebars | 1 -
.../templates/application-table-row.handlebars | 8 -
.../app/js/templates/application.handlebars | 50 -----
.../app/js/templates/container.handlebars | 10 -
.../app/js/templates/load-data-link.handlebars | 1 -
.../webapp/app/js/templates/movie.handlebars | 56 ------
.../app/js/view/application-table-paginator.js | 77 --------
.../webapp/app/js/view/application-table-row.js | 63 ------
.../src/main/webapp/app/js/view/application.js | 135 -------------
.../src/main/webapp/app/js/view/container.js | 62 ------
.../src/main/webapp/app/js/view/movie.js | 75 -------
examples/rest-mp-jwt/src/main/webapp/index.jsp | 36 ----
23 files changed, 1250 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/WEB-INF/web.xml b/examples/rest-mp-jwt/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index 328247d..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
-
- <!-- The trick is to put all your static files under the same directory and map the "default" servlet to it -->
- <servlet-mapping>
- <servlet-name>default</servlet-name>
- <url-pattern>/app/*</url-pattern>
- </servlet-mapping>
- <servlet-mapping>
- <servlet-name>default</servlet-name>
- <url-pattern>/webjars/*</url-pattern>
- </servlet-mapping>
-
- <!-- Any other request will point to the "index.jsp" page. This way Backbone knows how to manage page transitions
- at the client side in case the user starts the application from a permalink. -->
- <servlet>
- <servlet-name>application</servlet-name>
- <jsp-file>/index.jsp</jsp-file>
- </servlet>
- <servlet-mapping>
- <servlet-name>application</servlet-name>
- <url-pattern>/*</url-pattern>
- </servlet-mapping>
-
-</web-app>
-
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/app.less
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/app.less b/examples/rest-mp-jwt/src/main/webapp/app/app.less
deleted file mode 100644
index 61fd5e2..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/app.less
+++ /dev/null
@@ -1,62 +0,0 @@
-/*!
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-body {
- @content-margin-top: 80px;
-
- .ux-movie-window {
- .modal-dialog {
- padding-top: 90px;
- padding-bottom: 0px;
- }
- }
-
- .ux-landing {
- margin-top: @content-margin-top;
- }
-
- .ux-setup {
- margin-top: @content-margin-top;
- }
-
- .ux-application {
- margin-top: @content-margin-top;
-
- .pagination {
- margin-top: 0px;
- margin-bottom: 0px;
- }
-
- th:last-child {
- width: 5px;
- }
-
- .ux-add-btn {
- position: absolute;
- bottom: 20px;
- right: 30px;
- }
-
- a.ux-delete-row:hover, a.ux-edit-row:hover {
- cursor: hand;
- }
-
- .panel-body>.input-group {
- margin-bottom: 15px;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/config.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/config.js b/examples/rest-mp-jwt/src/main/webapp/app/config.js
deleted file mode 100644
index bbdc5e1..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/config.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var APP_CONFIG = {
- baseUrl: window.ux.ROOT_URL,
- paths: {
- 'text': 'webjars/requirejs-text/2.0.10/text',
- 'lib/less': 'webjars/less/1.6.0/less.min',
- 'lib/jquery': 'webjars/jquery/2.1.0/jquery.min',
- 'lib/bootstrap': 'webjars/bootstrap/3.1.0/js/bootstrap.min',
- 'lib/handlebars': 'webjars/handlebars/1.2.1/handlebars.min',
- 'lib/underscore': 'webjars/underscorejs/1.4.3/underscore-min',
- 'lib/json2': 'webjars/json2/20110223/json2.min',
- 'lib/backbone': 'webjars/backbonejs/1.0.0/backbone'
- },
- shim: {
- 'lib/bootstrap': {
- deps: ['lib/jquery']
- },
- 'lib/underscore': {
- exports: '_'
- },
- 'lib/backbone': {
- deps: ['lib/jquery', 'lib/json2', 'lib/underscore']
- },
- 'app/js/templates': {
- deps: ['lib/underscore', 'app/js/i18n']
- }
- }
-};
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/application.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/application.js b/examples/rest-mp-jwt/src/main/webapp/app/js/application.js
deleted file mode 100644
index 9ec4cab..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/application.js
+++ /dev/null
@@ -1,193 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-(function () {
- 'use strict';
-
- var deps = [
- 'app/js/view/container',
- 'app/js/view/application',
- 'app/js/view/application-table-paginator',
- 'app/js/view/movie',
- 'lib/underscore',
- 'app/js/model/movies',
- 'app/js/model/movie',
- 'app/js/i18n',
- 'lib/less', 'lib/backbone', 'lib/jquery', 'lib/bootstrap'
- ];
- define(deps, function (containerView, applicationView, paginator, MovieView, underscore, moviesList, MovieModel) {
- var max = 5;
- var appState = {
- page: null,
- fieldName: null,
- fieldValue: null
- };
- containerView.render();
-
- $.ajaxSetup({ cache: false });
-
- function loadPage(pageNumber, fieldName, fieldValue) {
- var data = {
- max: max,
- first: ((pageNumber - 1) * max)
- };
- if (fieldName && fieldValue) {
- data.field = fieldName;
- data.searchTerm = fieldValue;
- }
- applicationView.setFilter(fieldName, fieldValue);
- moviesList.fetch({
- data: data,
- success: function (result) {
- applicationView.addRows(result.models);
-
- $.ajax({
- url: window.ux.ROOT_URL + 'rest/movies/count/',
- method: 'GET',
- dataType: 'json',
- data: {
- field: appState.fieldName,
- searchTerm: appState.fieldValue
- },
- success: function (total) {
- var count = Math.ceil(total / max);
- paginator.setCount(count);
- applicationView.setPaginator(count);
- }
- });
- }
- });
- }
-
- function start() {
- //Starting the backbone router.
- var Router = Backbone.Router.extend({
- routes: {
- '': 'showApplication',
- 'application': 'showApplication',
- 'application/:page': 'showApplication',
- 'application/:page/:field/:value': 'showApplication'
- },
-
- showApplication: function (page, fieldName, fieldValue) {
- var me = this;
- appState.page = page;
- appState.fieldName = fieldName;
- appState.fieldValue = fieldValue;
- containerView.showView(applicationView);
- if (!page || !underscore.isNumber(Number(page))) {
- me.showApplication(1);
- } else {
- loadPage(Number(page), fieldName, fieldValue);
- if (fieldName) {
- me.navigate('application/' + page + '/' + fieldName + '/' + fieldValue, {
- trigger: false
- });
- } else {
- me.navigate('application/' + page, {
- trigger: false
- });
- }
- }
- }
- });
- var router = new Router();
-
- applicationView.on('load-sample', function () {
- $.ajax({
- url: window.ux.ROOT_URL + 'rest/load/',
- method: 'POST',
- dataType: 'json',
- data: {},
- success: function (data) {
- router.showApplication();
- }
- });
- });
-
- applicationView.on('delete', function (data) {
- data.model.destroy({
- success: function () {
- router.showApplication(appState.page, appState.fieldName, appState.fieldValue);
- }
- });
- });
-
- function showMovieWindow(model) {
- var view = new MovieView({
- model: model
- });
- view.render();
- view.on('save-model', function (data) {
- data.model.save({}, {
- success: function () {
- view.remove();
- loadPage(appState.page, appState.fieldName, appState.fieldValue);
- }
- });
- });
- $('body').append(view.$el);
- view.$el.modal({});
- }
-
- applicationView.on('add', function () {
- showMovieWindow(new MovieModel({}));
- });
-
- applicationView.on('edit', function (data) {
- showMovieWindow(data.model);
- });
-
- applicationView.on('filter', function (data) {
- router.navigate('application/1/' + data.filterType + '/' + data.filterValue, {
- trigger: true
- });
- });
-
- applicationView.on('clear-filter', function (data) {
- router.navigate('application/1', {
- trigger: true
- });
- });
-
- paginator.on('go-to-page', function (data) {
- var page = data.number;
- if (page === 'last') {
- page = paginator.getCount();
- }
- router.showApplication(page, appState.fieldName, appState.fieldValue);
- });
-
- //Starting the backbone history.
- Backbone.history.start({
- pushState: true,
- root: window.ux.ROOT_URL // This value is set by <c:url>
- });
-
- return {
- getRouter: function () {
- return router;
- }
- };
- }
-
- return {
- start: start
- };
- });
-}());
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/i18n.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/i18n.js b/examples/rest-mp-jwt/src/main/webapp/app/js/i18n.js
deleted file mode 100644
index 2603dec..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/i18n.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- "use strict";
- */
-
-define(['lib/underscore', 'lib/handlebars', 'app/js/log'], function (underscore) {
- 'use strict';
-
- var missing = Handlebars.compile('[!{{key}}!]');
- var messages = {
- 'application.name': 'Moviefun',
- 'load.dada': 'Click here to load sample data',
- 'movies': 'Movies',
- 'title': 'Title',
- 'director': 'Director',
- 'genre': 'Genre',
- 'rating': 'Rating',
- 'year': 'Year',
- 'add.movie': 'Add movie',
- 'movie': 'Movie',
- 'close': 'Close',
- 'save': 'Save',
-
- 'dummy': ''
- };
-
- underscore.each(underscore.keys(messages), function (key) {
- var template = Handlebars.compile(messages[key]);
- messages[key] = template;
- });
-
- var get = function (key, values) {
- var template = messages[key];
- var cfg = values;
- if (!template) {
- template = missing;
- cfg = {
- key: key
- };
- window.console.error('Missing i18n message.', key);
- }
- return template(cfg);
- };
-
- Handlebars.registerHelper('i18n', function (key) {
- return get(key);
- });
-
- return {
- get: get
- };
-});
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/id.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/id.js b/examples/rest-mp-jwt/src/main/webapp/app/js/id.js
deleted file mode 100644
index fc4c56a..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/id.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- "use strict";
- */
-
-define(['lib/underscore', 'lib/handlebars'], function (underscore) {
- 'use strict';
-
- var value = underscore.uniqueId('moviefun_');
-
- var current = function () {
- return value;
- };
- var next = function () {
- value = underscore.uniqueId('moviefun_');
- return value;
- };
- Handlebars.registerHelper('id_current', function (key) {
- return current();
- });
- Handlebars.registerHelper('id_next', function (key) {
- return next();
- });
-
- return {
- current: current,
- next: next
- };
-});
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/log.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/log.js b/examples/rest-mp-jwt/src/main/webapp/app/js/log.js
deleted file mode 100644
index 6e79b98..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/log.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-define([], function () {
- 'use strict';
-
- var noOp = function () {
- return ''; // no-op
- };
-
- if (!window.console) {
- window.console = {};
- }
-
- function createIfNull(functionName) {
- if (!window.console[functionName]) {
- window.console[functionName] = noOp;
- }
- }
-
- createIfNull('error');
- createIfNull('warn');
- createIfNull('log');
- createIfNull('info');
-});
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/model/movie.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/model/movie.js b/examples/rest-mp-jwt/src/main/webapp/app/js/model/movie.js
deleted file mode 100644
index 36be222..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/model/movie.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-(function () {
- 'use strict';
-
- var deps = ['lib/backbone'];
- define(deps, function () {
- var isString = function (obj) {
- return Object.prototype.toString.call(obj) === '[object String]';
- };
- return Backbone.Model.extend({
- urlRoot: window.ux.ROOT_URL + 'rest/movies',
- idAttribute: 'id',
- toJSON: function () {
- if (!!this.attributes.rating && isString(this.attributes.rating)) {
- this.attributes.rating = parseInt(this.attributes.rating, 10);
- }
- if (!!this.attributes.year && isString(this.attributes.year)) {
- this.attributes.year = parseInt(this.attributes.year, 10);
- }
- if (!!this.attributes.id && isString(this.attributes.id)) {
- this.attributes.id = parseInt(this.attributes.id, 10);
- }
- return this.attributes;
- },
- defaults: {
- rating: 5,
- year: new Date().getFullYear()
- }
- });
- });
-}());
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/model/movies.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/model/movies.js b/examples/rest-mp-jwt/src/main/webapp/app/js/model/movies.js
deleted file mode 100644
index 828d2f8..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/model/movies.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-(function () {
- 'use strict';
-
- var deps = ['app/js/model/movie', 'lib/backbone'];
- define(deps, function (Movie) {
- var Cls = Backbone.Collection.extend({
- model: Movie,
- url: window.ux.ROOT_URL + 'rest/movies',
- parse: function (response) {
- return response;
- }
- });
- return new Cls();
- });
-}());
-
-
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/start.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/start.js b/examples/rest-mp-jwt/src/main/webapp/app/js/start.js
deleted file mode 100644
index 33f7fbd..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/start.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-require.config(APP_CONFIG);
-
-requirejs(['app/js/application'], function (app) {
- 'use strict';
-
- $(window.document).ready(function () {
- // all the action is in app
- app.start();
- });
-});
-
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/templates.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates.js b/examples/rest-mp-jwt/src/main/webapp/app/js/templates.js
deleted file mode 100644
index e3f3300..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/templates.js
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-(function () {
- 'use strict';
-
- var files = [
- 'container',
- 'application',
- 'application-table-row',
- 'application-table-paginator-button',
- 'load-data-link',
- 'movie'
- ];
-
- function loop(values, callback) {
- var index;
- for (index = 0; index < values.length; index += 1) {
- callback(values[index], index);
- }
- }
-
- // Preparing the "requirements" paths.
- var requirements = [];
- loop(files, function (file) {
- requirements.push('text!app/js/templates/' + file + '.handlebars');
- });
-
- define(requirements, function () {
- var templates = {};
-
- var myArgs = arguments;
- loop(files, function (file, i) {
- templates[file] = Handlebars.compile(myArgs[i]);
- });
-
- return {
- getValue: function (templateName, cfg) {
- var template = templates[templateName];
- if (!template) {
- throw 'Template not registered. "' + templateName + '"';
- }
- var result;
- if (cfg) {
- result = template(cfg);
- } else {
- result = template({});
- }
- return result;
- }
- };
- });
-}());
-
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-paginator-button.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-paginator-button.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-paginator-button.handlebars
deleted file mode 100644
index 0031aba..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-paginator-button.handlebars
+++ /dev/null
@@ -1 +0,0 @@
-<li><a href="{{pageNumber}}">{{pageText}}</a></li>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-row.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-row.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-row.handlebars
deleted file mode 100644
index dc9bf7c..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-row.handlebars
+++ /dev/null
@@ -1,8 +0,0 @@
-<td><a href="edit" class="ux-edit-row">{{title}}</a></td>
-<td>{{director}}</td>
-<td>{{genre}}</td>
-<td>{{rating}}</td>
-<td>{{year}}</td>
-<td>
- <a href="delete" class="ux-delete-row"><span class="glyphicon glyphicon-trash"></span></a>
-</td>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application.handlebars
deleted file mode 100644
index f15d1a9..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application.handlebars
+++ /dev/null
@@ -1,50 +0,0 @@
-<div class="row">
- <div class="col-md-12">
- <div class="panel panel-default">
- <div class="panel-heading">
- <h3 class="panel-title">{{i18n "movies"}}</h3>
- </div>
- <div class="panel-body">
- <div class="input-group">
- <div class="input-group-btn">
- <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
- <span class="ux-selected-filter">{{i18n "title"}}</span> <span class="caret"></span>
- </button>
- <ul class="dropdown-menu" role="menu">
- <li><a href="title" class="ux-filter">{{i18n "title"}}</a></li>
- <li><a href="director" class="ux-filter">{{i18n "director"}}</a></li>
- <li><a href="genre" class="ux-filter">{{i18n "genre"}}</a></li>
- <li><a href="rating" class="ux-filter">{{i18n "rating"}}</a></li>
- <li><a href="year" class="ux-filter">{{i18n "year"}}</a></li>
- </ul>
- </div><!-- /btn-group -->
- <input type="text" class="form-control ux-filter-field">
- <span class="input-group-btn">
- <button class="btn btn-primary ux-clear-filter-action" type="button">
- <span class="glyphicon glyphicon-remove-circle"></span>
- </button>
- <button class="btn btn-primary ux-filter-action" type="button">
- <span class="glyphicon glyphicon-search"></span>
- </button>
- </span>
- </div>
- <table class="table table-bordered table-striped table-hover">
- <thead>
- <tr>
- <th>{{i18n "title"}}</th>
- <th>{{i18n "director"}}</th>
- <th>{{i18n "genre"}}</th>
- <th>{{i18n "rating"}}</th>
- <th>{{i18n "year"}}</th>
- <th></th>
- </tr>
- </thead>
- <tbody></tbody>
- </table>
- <button type="button" class="btn btn-primary ux-add-btn">{{i18n "add.movie"}}</button>
- </div>
- </div>
- </div>
-</div>
-
-
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/templates/container.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/container.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/container.handlebars
deleted file mode 100644
index dba60dd..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/container.handlebars
+++ /dev/null
@@ -1,10 +0,0 @@
-<div class="navbar navbar-inverse navbar-fixed-top">
- <div class="container">
- <div class="navbar-header">
- <a class="navbar-brand" href="#">{{i18n "application.name"}}</a>
- </div>
- </div>
-</div>
-<div class="container">
- <div class="ux-contentarea"></div>
-</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/templates/load-data-link.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/load-data-link.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/load-data-link.handlebars
deleted file mode 100644
index 1785578..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/load-data-link.handlebars
+++ /dev/null
@@ -1 +0,0 @@
-<a href="load-data">{{i18n "load.dada"}}</a>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/templates/movie.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/movie.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/movie.handlebars
deleted file mode 100644
index 97c511c..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/movie.handlebars
+++ /dev/null
@@ -1,56 +0,0 @@
-<div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
- <h4 class="modal-title">{{i18n "movie"}}</h4>
- </div>
- <div class="modal-body">
- <form class="form-horizontal" role="form">
- <div class="form-group">
- <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "title"}}</label>
-
- <div class="col-lg-10">
- <input class="form-control ux-title" id="{{id_current}}" placeholder="{{i18n 'title'}}"
- type="text" value="{{title}}">
- </div>
- </div>
- <div class="form-group">
- <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "director"}}</label>
-
- <div class="col-lg-10">
- <input class="form-control ux-director" id="{{id_current}}"
- type="text" placeholder="{{i18n 'director'}}" value="{{director}}">
- </div>
- </div>
- <div class="form-group">
- <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "genre"}}</label>
-
- <div class="col-lg-10">
- <input class="form-control ux-genre" id="{{id_current}}" placeholder="{{i18n 'genre'}}"
- type="text" value="{{genre}}">
- </div>
- </div>
- <div class="form-group">
- <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "rating"}}</label>
-
- <div class="col-lg-10">
- <input class="form-control ux-rating" id="{{id_current}}"
- type="number" min="0" max="10" placeholder="{{i18n 'rating'}}" value="{{rating}}">
- </div>
- </div>
- <div class="form-group">
- <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "year"}}</label>
-
- <div class="col-lg-10">
- <input class="form-control ux-year" id="{{id_current}}" placeholder="{{i18n 'year'}}"
- type="number" min="1900" max="{{currentYear}}" value="{{year}}">
- </div>
- </div>
- </form>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default ux-close" data-dismiss="modal">{{i18n "close"}}</button>
- <button type="button" class="btn btn-primary ux-save" data-dismiss="modal">{{i18n "save"}}</button>
- </div>
- </div>
-</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-paginator.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-paginator.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-paginator.js
deleted file mode 100644
index c5d2422..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-paginator.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-(function () {
- 'use strict';
-
- var deps = ['app/js/templates', 'lib/backbone'];
- define(deps, function (templates) {
-
- var View = Backbone.View.extend({
- tagName: 'ul',
- className: 'pagination',
-
- count: 0,
-
- events: {
- 'click a': function (evt) {
- evt.preventDefault();
- var me = this;
- var myLink = $(evt.target);
- var href = myLink.attr('href');
- me.trigger('go-to-page', {
- number: href
- });
- }
- },
-
- render: function () {
- var me = this;
- me.$el.empty();
- me.$el.append(templates.getValue('application-table-paginator-button', {
- pageNumber: '1',
- pageText: '<<'
- }));
- var i;
- for (i = 1; i < me.count + 1; i += 1) {
- me.$el.append(templates.getValue('application-table-paginator-button', {
- pageNumber: i,
- pageText: i
- }));
- }
- me.$el.append(templates.getValue('application-table-paginator-button', {
- pageNumber: 'last',
- pageText: '>>'
- }));
- return this;
- },
-
- setCount: function (count) {
- var me = this;
- me.count = count;
- me.render();
- },
-
- getCount: function () {
- var me = this;
- return me.count;
- }
- });
- return new View().render();
- });
-}());
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-row.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-row.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-row.js
deleted file mode 100644
index 771a062..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-row.js
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-(function () {
- 'use strict';
-
- var deps = ['app/js/templates', 'lib/backbone'];
- define(deps, function (templates) {
-
- var View = Backbone.View.extend({
- tagName: 'tr',
- events: {
- 'click .ux-delete-row': function (evt) {
- evt.preventDefault();
- var me = this;
- me.trigger('delete', {
- model: me.model
- });
- me.remove();
- },
- 'click .ux-edit-row': function (evt) {
- evt.preventDefault();
- var me = this;
- me.trigger('edit', {
- model: me.model
- });
- }
- },
-
- render: function () {
- var me = this;
- if (!this.options.isRendered) {
- me.$el.empty();
- me.$el.append(templates.getValue('application-table-row', {
- title: me.model.get('title'),
- director: me.model.get('director'),
- genre: me.model.get('genre'),
- rating: me.model.get('rating'),
- year: me.model.get('year')
- }));
- me.options.isRendered = true;
- }
- return this;
- }
- });
- return View;
- });
-}());
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/view/application.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/application.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application.js
deleted file mode 100644
index 7dae6b3..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/view/application.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-(function () {
- 'use strict';
-
- var deps = ['app/js/templates', 'app/js/view/application-table-row', 'app/js/view/application-table-paginator',
- 'lib/underscore', 'app/js/i18n', 'lib/backbone'];
- define(deps, function (templates, TableRowView, paginator, underscore, i18n) {
-
- var View = Backbone.View.extend({
- tagName: 'div',
- className: 'ux-application',
-
- loadDataLink: $(templates.getValue('load-data-link', {})),
-
- filterOption: 'title',
-
- events: {
- 'click .ux-filter': function (evt) {
- evt.preventDefault();
- var me = this;
- var selected = $(me.$el.find('.ux-selected-filter').get(0));
- var myLink = $(evt.target);
- me.filterOption = myLink.attr('href');
- selected.html(i18n.get(me.filterOption, {}));
- },
- 'click .ux-filter-action': function (evt) {
- evt.preventDefault();
- var me = this;
- var filterValue = $(me.$el.find('.ux-filter-field').get(0)).val();
- filterValue = $.trim(filterValue);
- if (filterValue !== '') {
- me.trigger('filter', {
- filterType: me.filterOption,
- filterValue: filterValue
- });
- }
- },
- 'click .ux-clear-filter-action': function (evt) {
- evt.preventDefault();
- var me = this;
- me.trigger('clear-filter', {});
- },
- 'click .ux-application': function (evt) {
- evt.preventDefault();
- var me = this;
- me.trigger('navigate', {
- path: 'application'
- });
- },
- 'click .ux-add-btn': function (evt) {
- evt.preventDefault();
- var me = this;
- me.trigger('add', {});
- }
- },
-
- setFilter: function (fieldName, fieldValue) {
- var field = fieldName;
- var value = fieldValue;
- if (!fieldName || $.trim(fieldName) === '') {
- field = 'title';
- value = '';
- }
- var me = this;
- me.filterOption = field;
- $(me.$el.find('.ux-selected-filter').get(0)).html(i18n.get(me.filterOption, {}));
- $(me.$el.find('.ux-filter-field').get(0)).val(value);
- },
-
- render: function () {
- var me = this;
- if (!this.options.isRendered) {
- me.$el.empty();
- me.$el.append(templates.getValue('application', {}));
- me.loadDataLink.on('click', function (evt) {
- evt.preventDefault();
- me.trigger('load-sample', {});
- });
- me.options.isRendered = true;
- }
- return this;
- },
-
- addRows: function (rows) {
- var me = this;
- var tbody = $(me.$el.find('tbody').get(0));
- tbody.empty();
- paginator.$el.detach();
- me.loadDataLink.detach();
- underscore.each(rows, function (model) {
- var row = new TableRowView({
- model: model
- });
- row.on('delete', function (data) {
- me.trigger('delete', data);
- });
- row.on('edit', function (data) {
- me.trigger('edit', data);
- });
- tbody.append(row.render().$el);
- });
- },
-
- setPaginator: function (count) {
- var me = this;
- paginator.$el.detach();
- me.loadDataLink.detach();
- var table = $(me.$el.find('.table').get(0));
- if (count) {
- table.after(paginator.$el);
- } else {
- table.after(me.loadDataLink);
- }
- }
- });
- return new View();
- });
-}());
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/view/container.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/container.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/container.js
deleted file mode 100644
index 73a57f1..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/view/container.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-(function () {
- 'use strict';
-
- var deps = ['app/js/templates', 'app/js/i18n', 'lib/backbone'];
- define(deps, function (templates) {
-
- var View = Backbone.View.extend({
- el: 'body',
-
- showView: function (view) {
- var me = this;
- var contentarea = me.$('.ux-contentarea');
- if (me.currentView) {
- me.currentView.$el.detach();
- }
- me.currentView = view;
- me.currentView.render();
- contentarea.append(me.currentView.el);
- if (view.renderCallback) {
- view.renderCallback();
- }
- me.$('.ux-app-menu-item').removeClass('active');
- var myMenuItem = me.$('li.ux-app-menu-item.' + view.className);
- myMenuItem.addClass('active');
- },
-
- render: function () {
- if (this.options.isRendered) {
- return this;
- }
- var html = templates.getValue('container', {
- userName: ''
- });
- this.$el.html(html);
-
- // render it only once
- this.options.isRendered = true;
- return this;
- }
- });
-
- return new View({});
- });
-}());
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/app/js/view/movie.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/movie.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/movie.js
deleted file mode 100644
index 0417945..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/app/js/view/movie.js
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-(function () {
- 'use strict';
-
- var deps = ['app/js/templates', 'lib/underscore', 'lib/backbone', 'app/js/id'];
- define(deps, function (templates, underscore) {
-
- var View = Backbone.View.extend({
- tagName: 'div',
- className: 'modal ux-movie-window',
- events: {
- 'click .ux-application': function (evt) {
- evt.preventDefault();
- var me = this;
- me.trigger('show-application', {});
- },
- 'click .ux-close': function (evt) {
- evt.preventDefault();
- var me = this;
- me.remove();
- },
- 'click .ux-save': function (evt) {
- evt.preventDefault();
- var me = this;
- var model = me.model;
-
- function set(name) {
- var field = $(me.$el.find('.ux-' + name).get(0));
- model.set(name, field.val());
- }
-
- set('title');
- set('director');
- set('genre');
- set('rating');
- set('year');
- me.trigger('save-model', {
- model: model
- });
- }
- },
- render: function () {
- var me = this;
- me.$el.empty();
- me.$el.append(templates.getValue('movie', {
- title: me.model.get('title'),
- director: me.model.get('director'),
- genre: me.model.get('genre'),
- rating: me.model.get('rating'),
- year: me.model.get('year'),
- currentYear: new Date().getFullYear()
- }));
- return me;
- }
- });
- return View;
- });
-}());
http://git-wip-us.apache.org/repos/asf/tomee/blob/3e579aad/examples/rest-mp-jwt/src/main/webapp/index.jsp
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/index.jsp b/examples/rest-mp-jwt/src/main/webapp/index.jsp
deleted file mode 100644
index 63d3e42..0000000
--- a/examples/rest-mp-jwt/src/main/webapp/index.jsp
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<%@ page contentType="text/html;charset=UTF-8" language="java" %>
-<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
-<html lang="en">
-<head>
- <meta charset="utf-8">
- <title>Moviefun</title>
- <link href="<c:url value='/webjars/bootstrap/3.1.0/css/bootstrap.min.css'/>" rel="stylesheet">
- <link href="<c:url value='/app/app.less'/>" rel="stylesheet/less" type="text/css">
- <script src="<c:url value='/webjars/requirejs/2.1.10/require.min.js'/>"></script>
- <script type="text/javascript">
- window.ux = window.ux || {};
- window.ux.SESSION_ID = "<%=request.getSession().getId()%>";
- window.ux.ROOT_URL = "<c:url value='/'/>".replace(';jsessionid=' + window.ux.SESSION_ID, '');
- </script>
- <script src="<c:url value='/app/config.js'/>"></script>
- <script src="<c:url value='/app/js/start.js'/>"></script>
-</head>
-<body></body>
-</html>
\ No newline at end of file