Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of EntityPart API #4859

Merged
merged 2 commits into from
Sep 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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