Skip to content

Commit

Permalink
Implementation of EntityPart API (#4859)
Browse files Browse the repository at this point in the history
* Implementation of EntityPart API

Signed-off-by: jansupol <[email protected]>
  • Loading branch information
jansupol committed Sep 22, 2021
1 parent e92e025 commit 552fb69
Show file tree
Hide file tree
Showing 29 changed files with 1,275 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.jersey.innate.multipart;

import jakarta.ws.rs.core.EntityPart;

import java.lang.reflect.Type;

/**
* Jersey extended {@code EntityPart}. Contains arbitrary useful methods.
*
* @since 3.1.0
*/
public interface JerseyEntityPart extends EntityPart {
/**
* Converts the content stream for this part to the specified class and returns
* it.
*
* Subsequent invocations will result in an {@code IllegalStateException}.
* Likewise this method will throw an {@code IllegalStateException} if it is called after calling
* {@link #getContent} or similar {@code getContent} method.
*
* @param <T> type parameter of the value returned
* @param type the {@code Class} that the implementation should convert this
* part to
* @param <T> the entity type
* @return an instance of the specified {@code Class} representing the content
* of this part
* @throws IllegalStateException if this method or any of the other
* {@code getContent} methods has already been
* invoked
*/
<T> T getContent(Class<T> type, Type genericType);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

/**
* Multipart Jersey innate classes. This innate package will be opened by JPMS only to Jersey-media-multipart.
*/
package org.glassfish.jersey.innate.multipart;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

/**
* Jersey innate packages. The innate packages will not be opened by JPMS outside of Jersey.
*/
package org.glassfish.jersey.innate;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.innate.spi;

import jakarta.ws.rs.core.EntityPart;

/**
* Jersey extension of provider of EntityPart.Builder.
* A service meant to be implemented solely by Jersey.
*
* @since 3.1.0
*/
public interface EntityPartBuilderProvider {

/**
* @param partName name of the part to create within the multipart entity.
* @return {@link EntityPart.Builder} for building new {@link EntityPart} instances.
*/
public EntityPart.Builder withName(String partName);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

/**
* Common Jersey innate SPI classes. The innate package will not be opened by JPMS.
*/
package org.glassfish.jersey.innate.spi;
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,20 @@
import jakarta.ws.rs.core.CacheControl;
import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.Cookie;
import jakarta.ws.rs.core.EntityPart;
import jakarta.ws.rs.core.EntityTag;
import jakarta.ws.rs.core.Link;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.NewCookie;
import jakarta.ws.rs.core.Response.ResponseBuilder;
import jakarta.ws.rs.core.UriBuilder;
import jakarta.ws.rs.ext.ParamConverter;
import jakarta.ws.rs.ext.RuntimeDelegate;

import org.glassfish.jersey.innate.spi.EntityPartBuilderProvider;
import org.glassfish.jersey.internal.util.collection.LazyValue;
import org.glassfish.jersey.internal.util.collection.Value;
import org.glassfish.jersey.internal.util.collection.Values;
import org.glassfish.jersey.message.internal.JerseyLink;
import org.glassfish.jersey.message.internal.OutboundJaxrsResponse;
import org.glassfish.jersey.message.internal.OutboundMessageContext;
Expand All @@ -50,6 +56,8 @@ public abstract class AbstractRuntimeDelegate extends RuntimeDelegate {

private final Set<HeaderDelegateProvider> hps;
private final Map<Class<?>, HeaderDelegate<?>> map;
private LazyValue<EntityPartBuilderProvider> entityPartBuilderProvider = Values.lazy(
(Value<EntityPartBuilderProvider>) () -> findEntityPartBuilderProvider());

/**
* Initialization constructor. The injection manager will be shut down.
Expand Down Expand Up @@ -117,4 +125,24 @@ private <T> HeaderDelegate<T> _createHeaderDelegate(final Class<T> type) {

return null;
}

@Override
public EntityPart.Builder createEntityPartBuilder(String partName) throws IllegalArgumentException {
return entityPartBuilderProvider.get().withName(partName);
}

/**
* Obtain a {@code RuntimeDelegate} instance using the method described in {@link #getInstance}.
*
* @return an instance of {@code RuntimeDelegate}.
*/
private static EntityPartBuilderProvider findEntityPartBuilderProvider() {
for (final EntityPartBuilderProvider entityPartBuilder : ServiceFinder.find(EntityPartBuilderProvider.class)) {
if (entityPartBuilder != null) {
return entityPartBuilder;
}
}

throw new IllegalArgumentException(LocalizationMessages.NO_ENTITYPART_BUILDER_FOUND());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,6 @@ public CompletionStage<SeBootstrap.Instance> bootstrap(Application application,
throw new UnsupportedOperationException(LocalizationMessages.NO_CONTAINER_AVAILABLE());
}

@Override
public EntityPart.Builder createEntityPartBuilder(String partName) throws IllegalArgumentException {
final RuntimeDelegate runtimeDelegate = findServerDelegate();
if (runtimeDelegate != null) {
return runtimeDelegate.createEntityPartBuilder(partName);
}
throw new UnsupportedOperationException(LocalizationMessages.NO_CONTAINER_AVAILABLE());
}

// TODO : Do we need multiple RuntimeDelegates?
private RuntimeDelegate findServerDelegate() {
for (RuntimeDelegate delegate : ServiceFinder.find(RuntimeDelegate.class)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@

package org.glassfish.jersey.internal.inject;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.text.ParseException;
import java.util.Date;
Expand Down Expand Up @@ -255,6 +259,39 @@ public String toString(final T value) throws IllegalArgumentException {
}
}

/**
* Provider of {@link ParamConverter param converter} that convert the supplied string into a Java
* {@link InputStream} instance.
*/
public static class InputStreamProvider implements ParamConverterProvider {

@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
return rawType != InputStream.class ? null : new ParamConverter<T>() {

@Override
public T fromString(String value) {
if (value == null) {
throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value"));
}
return rawType.cast(new ByteArrayInputStream(value.getBytes(StandardCharsets.UTF_8)));
}

@Override
public String toString(T value) {
if (value == null) {
throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value"));
}
try {
return new String(((InputStream) value).readAllBytes());
} catch (IOException ioe) {
throw new ExtractorException(ioe);
}
}
};
}
}

/**
* Provider of {@link ParamConverter param converter} that produce the Optional instance
* by invoking {@link ParamConverterProvider}.
Expand Down Expand Up @@ -414,6 +451,7 @@ public AggregatedProvider(InjectionManager manager) {
new TypeFromStringEnum(),
new TypeValueOf(),
new CharacterProvider(),
new InputStreamProvider(),
new TypeFromString(),
new StringConstructor(),
new OptionalCustomProvider(manager),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2018 Payara Foundation and/or its affiliates.
#
# This program and the accompanying materials are made available under the
Expand Down Expand Up @@ -116,6 +116,7 @@ multiple.matching.constructors.found=Found {0} constructors with {1} parameters
new.cookie.is.null=New cookie is null.
no.container.available=No container available.
no.error.processing.in.scope=There is no error processing in scope.
no.entitypart.builder.found="No EntityPart.Builder implementation found. Is jersey-media-multipart on a classpath?";
not.supported.on.outbound.message=Method not supported on an outbound message.
osgi.registry.error.opening.resource.stream=Unable to open an input stream for resource {0}.
osgi.registry.error.processing.resource.stream=Unexpected error occurred while processing resource stream {0}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,6 @@ public CompletionStage<SeBootstrap.Instance> bootstrap(Application application,
throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public EntityPart.Builder createEntityPartBuilder(String partName) throws IllegalArgumentException {
throw new UnsupportedOperationException("Not supported yet.");
}

public void testMediaType() {
MediaType m = new MediaType("text", "plain");
Assert.assertNotNull(m);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,4 @@ public final <T> T unwrap(final Class<T> nativeClass) {
};
});
}

@Override
public EntityPart.Builder createEntityPartBuilder(String partName) throws IllegalArgumentException {
throw new UnsupportedOperationException("Not supported yet.");
}

}
Loading

0 comments on commit 552fb69

Please sign in to comment.