diff --git a/opendj-cli/src/main/java/com/forgerock/opendj/cli/CliConstants.java b/opendj-cli/src/main/java/com/forgerock/opendj/cli/CliConstants.java index 9877dfebdf..00132f6870 100644 --- a/opendj-cli/src/main/java/com/forgerock/opendj/cli/CliConstants.java +++ b/opendj-cli/src/main/java/com/forgerock/opendj/cli/CliConstants.java @@ -22,7 +22,7 @@ public final class CliConstants { /** The minimum java specification supported string version. */ - public static final float MINIMUM_JAVA_VERSION = 1.8F; + public static final float MINIMUM_JAVA_VERSION = 8f; /** Default value for LDAP connection timeout. */ public static final int DEFAULT_LDAP_CONNECT_TIMEOUT = 30000; diff --git a/opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java b/opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java index a4d48f0402..52381d35ff 100644 --- a/opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java +++ b/opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java @@ -378,7 +378,7 @@ public static String wrapText(final String text, int width, final int indent) { * If the java version we are running on is not compatible. */ public static void checkJavaVersion() throws ClientException { - final String version = System.getProperty("java.specification.version"); + final String version = System.getProperty("java.specification.version").replaceAll("^1\\.", ""); if (Float.valueOf(version) < CliConstants.MINIMUM_JAVA_VERSION) { final String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; throw new ClientException(ReturnCode.JAVA_VERSION_INCOMPATIBLE, diff --git a/opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/rest2ldap/endpoints/api/example-v1.json b/opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/rest2ldap/endpoints/api/example-v1.json index b5a0b02bc3..096de36f7e 100644 --- a/opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/rest2ldap/endpoints/api/example-v1.json +++ b/opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/rest2ldap/endpoints/api/example-v1.json @@ -21,18 +21,6 @@ "dnAttribute": "uid" } }, - // This resource is the same as "users", but read-only. - // Users cannot be created, modified, or deleted through this sub-resource. - "read-only-users": { - "type": "collection", - "dnTemplate": "ou=people,dc=example,dc=com", - "resource": "frapi:opendj:rest2ldap:user:1.0", - "namingStrategy": { - "type": "clientDnNaming", - "dnAttribute": "uid" - }, - "isReadOnly": true - }, "groups": { "type": "collection", "dnTemplate": "ou=groups,dc=example,dc=com", diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectPropertyMapper.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectPropertyMapper.java index d98b69445a..94f3895236 100644 --- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectPropertyMapper.java +++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectPropertyMapper.java @@ -317,8 +317,8 @@ Promise read(final Context context, final Resource @Override public JsonValue apply(final List> value) { if (value.isEmpty()) { - // No subordinate attributes, so omit the entire JSON object from the resource. - return null; + // No subordinate attributes, we can return empty object. + return new JsonValue(Collections.emptyMap()); } else { // Combine the sub-attributes into a single JSON object. final Map result = new LinkedHashMap<>(value.size()); diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReadOnlyRequestHandler.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReadOnlyRequestHandler.java index 71435591cf..1c16427982 100644 --- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReadOnlyRequestHandler.java +++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReadOnlyRequestHandler.java @@ -18,8 +18,6 @@ import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.ERR_READ_ONLY_ENDPOINT; -import org.forgerock.api.models.ApiDescription; -import org.forgerock.http.ApiProducer; import org.forgerock.json.resource.BadRequestException; import org.forgerock.json.resource.QueryRequest; import org.forgerock.json.resource.QueryResourceHandler; @@ -30,7 +28,6 @@ import org.forgerock.json.resource.ResourceException; import org.forgerock.json.resource.ResourceResponse; import org.forgerock.services.context.Context; -import org.forgerock.services.descriptor.Describable; import org.forgerock.util.promise.Promise; /** @@ -59,14 +56,4 @@ public Promise handleRead( protected Promise handleRequest(final Context context, final Request request) { return new BadRequestException(ERR_READ_ONLY_ENDPOINT.get().toString()).asPromise(); } - - @Override - public ApiDescription api(ApiProducer producer) { - if (delegate instanceof Describable) { - return ((Describable)delegate).api(producer); - } - else { - return super.api(producer); - } - } } diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Resource.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Resource.java index 35825f6c6c..9c8fbd0a51 100644 --- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Resource.java +++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Resource.java @@ -470,31 +470,6 @@ String getResourceId() { return id; } - /** - * Gets a unique name for the configuration of this resource as a service in CREST. - * - * The name is the combination of the resource type and the writability of the resource. For - * example, {@code frapi:opendj:rest2ldap:group:1.0:read-write} or - * {@code frapi:opendj:rest2ldap:user:1.0:read-only}. Multiple resources can share the same - * service description if they manipulate the same resource type and have the same writability. - * - * @param isReadOnly - * Whether or not this resource is read-only. - * - * @return The unique service ID for this resource, given the specified writability. - */ - String getServiceId(boolean isReadOnly) { - StringBuilder serviceId = new StringBuilder(this.getResourceId()); - - if (isReadOnly) { - serviceId.append(":read-only"); - } else { - serviceId.append(":read-write"); - } - - return serviceId.toString(); - } - void build(final Rest2Ldap rest2Ldap) { // Prevent re-entrant calls. if (isBuilt) { @@ -547,7 +522,7 @@ ApiDescription instanceApi(boolean isReadOnly) { org.forgerock.api.models.Resource.Builder resource = org.forgerock.api.models.Resource. resource() - .title(this.getServiceId(isReadOnly)) + .title(id) .description(toLS(description)) .resourceSchema(schemaRef("#/definitions/" + id)) .mvccSupported(isMvccSupported()); @@ -564,8 +539,8 @@ ApiDescription instanceApi(boolean isReadOnly) { return ApiDescription.apiDescription() .id("unused").version("unused") .definitions(definitions()) - .services(services(resource, isReadOnly)) - .paths(paths(isReadOnly)) + .services(services(resource)) + .paths(paths()) .errors(errors()) .build(); } @@ -580,17 +555,13 @@ ApiDescription instanceApi(boolean isReadOnly) { ApiDescription collectionApi(boolean isReadOnly) { org.forgerock.api.models.Resource.Builder resource = org.forgerock.api.models.Resource. resource() - .title(this.getServiceId(isReadOnly)) + .title(id) .description(toLS(description)) .resourceSchema(schemaRef("#/definitions/" + id)) .mvccSupported(isMvccSupported()); resource.items(buildItems(isReadOnly)); - - if (!isReadOnly) { - resource.create(createOperation(CreateMode.ID_FROM_SERVER)); - } - + resource.create(createOperation(CreateMode.ID_FROM_SERVER)); resource.query(Query.query() .stability(EVOLVING) .type(QueryType.FILTER) @@ -609,29 +580,23 @@ ApiDescription collectionApi(boolean isReadOnly) { return ApiDescription.apiDescription() .id("unused").version("unused") .definitions(definitions()) - .services(services(resource, isReadOnly)) - .paths(paths(isReadOnly)) + .services(services(resource)) + .paths(paths()) .errors(errors()) .build(); } - private Services services(org.forgerock.api.models.Resource.Builder resource, - boolean isReadOnly) { - final String serviceId = this.getServiceId(isReadOnly); - + private Services services(org.forgerock.api.models.Resource.Builder resource) { return Services.services() - .put(serviceId, resource.build()) + .put(id, resource.build()) .build(); } - private Paths paths(boolean isReadOnly) { - final String serviceId = this.getServiceId(isReadOnly); - final org.forgerock.api.models.Resource resource = resourceRef("#/services/" + serviceId); - + private Paths paths() { return Paths.paths() // do not put anything in the path to avoid unfortunate string concatenation // also use UNVERSIONED and rely on the router to stamp the version - .put("", versionedPath().put(UNVERSIONED, resource).build()) + .put("", versionedPath().put(UNVERSIONED, resourceRef("#/services/" + id)).build()) .build(); } diff --git a/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/Rest2LdapJsonConfiguratorTest.java b/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/Rest2LdapJsonConfiguratorTest.java index 30c72138f5..b94fdf6498 100644 --- a/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/Rest2LdapJsonConfiguratorTest.java +++ b/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/Rest2LdapJsonConfiguratorTest.java @@ -24,7 +24,6 @@ import static org.forgerock.util.Options.defaultOptions; import java.io.File; -import java.io.IOException; import java.io.StringReader; import java.nio.file.Path; import java.nio.file.Paths; @@ -32,9 +31,6 @@ import org.forgerock.api.CrestApiProducer; import org.forgerock.api.models.ApiDescription; -import org.forgerock.api.models.Items; -import org.forgerock.api.models.Resource; -import org.forgerock.api.models.Services; import org.forgerock.http.routing.UriRouterContext; import org.forgerock.http.util.Json; import org.forgerock.json.JsonValue; @@ -64,11 +60,8 @@ public class Rest2LdapJsonConfiguratorTest extends ForgeRockTestCase { @Test public void testConfigureEndpointsWithApiDescription() throws Exception { - final DescribableRequestHandler handler = - createDescribableHandler(CONFIG_DIR.resolve("endpoints").toFile()); - + final DescribableRequestHandler handler = configureEndpoints(CONFIG_DIR.resolve("endpoints").toFile()); final ApiDescription api = requestApi(handler, "api/users/bjensen"); - assertThat(api).isNotNull(); // Ensure we can can pretty print and parse back the generated api description @@ -76,103 +69,42 @@ public void testConfigureEndpointsWithApiDescription() throws Exception { assertThat(api.getId()).isEqualTo(ID); assertThat(api.getVersion()).isEqualTo(VERSION); - - assertThat(api.getPaths().getNames()).containsOnly( - "/api/users", - "/api/read-only-users", - "/api/groups"); - + assertThat(api.getPaths().getNames()).containsOnly("/api/users", "/api/groups"); assertThat(api.getDefinitions().getNames()).containsOnly( "frapi:opendj:rest2ldap:object:1.0", "frapi:opendj:rest2ldap:group:1.0", "frapi:opendj:rest2ldap:user:1.0", "frapi:opendj:rest2ldap:posixUser:1.0"); - - final Services services = api.getServices(); - - assertThat(services.getNames()).containsOnly( - "frapi:opendj:rest2ldap:user:1.0:read-write", - "frapi:opendj:rest2ldap:user:1.0:read-only", - "frapi:opendj:rest2ldap:group:1.0:read-write"); - - final String[] readOnlyServices = new String[] { - "frapi:opendj:rest2ldap:user:1.0:read-only" - }; - - for (String serviceName : readOnlyServices) { - final Resource service = services.get(serviceName); - final Items items = service.getItems(); - - assertThat(service.getCreate()).isNull(); - assertThat(items.getCreate()).isNull(); - assertThat(items.getUpdate()).isNull(); - assertThat(items.getDelete()).isNull(); - assertThat(items.getPatch()).isNull(); - - assertThat(items.getRead()).isNotNull(); - } - - final String[] writableServices = new String[] { - "frapi:opendj:rest2ldap:user:1.0:read-write", - "frapi:opendj:rest2ldap:group:1.0:read-write" - }; - - for (String serviceName : writableServices) { - final Resource service = services.get(serviceName); - final Items items = service.getItems(); - - assertThat(service.getCreate()).isNotNull(); - assertThat(items.getCreate()).isNotNull(); - assertThat(items.getUpdate()).isNotNull(); - assertThat(items.getDelete()).isNotNull(); - assertThat(items.getPatch()).isNotNull(); - assertThat(items.getRead()).isNotNull(); - } } - private RequestHandler createRequestHandler(final File endpointsDir) throws IOException { - return Rest2LdapJsonConfigurator.configureEndpoints(endpointsDir, Options.defaultOptions()); - } - - private DescribableRequestHandler createDescribableHandler(final File endpointsDir) - throws Exception { - final RequestHandler rh = createRequestHandler(endpointsDir); - final DescribableRequestHandler handler = new DescribableRequestHandler(rh); - + private DescribableRequestHandler configureEndpoints(final File endpointsDir) throws Exception { + final RequestHandler rh = Rest2LdapJsonConfigurator.configureEndpoints(endpointsDir, Options.defaultOptions()); + DescribableRequestHandler handler = new DescribableRequestHandler(rh); handler.api(new CrestApiProducer(ID, VERSION)); - return handler; } - private ApiDescription requestApi(final DescribableRequestHandler handler, - final String uriPath) { - final Context context = newRouterContext(uriPath); - final Request request = newApiRequest(resourcePath(uriPath)); - + private ApiDescription requestApi(final DescribableRequestHandler handler, String uriPath) { + Context context = newRouterContext(uriPath); + Request request = newApiRequest(resourcePath(uriPath)); return handler.handleApiRequest(context, request); } private Context newRouterContext(final String uriPath) { Context ctx = new RootContext(); - ctx = new Rest2LdapContext(ctx, rest2Ldap(defaultOptions())); ctx = new UriRouterContext(ctx, null, uriPath, Collections. emptyMap()); - return ctx; } private String prettyPrint(Object o) throws Exception { final ObjectMapper objectMapper = - new ObjectMapper().registerModules( - new Json.LocalizableStringModule(), - new Json.JsonValueModule()); - + new ObjectMapper().registerModules(new Json.LocalizableStringModule(), new Json.JsonValueModule()); final ObjectWriter writer = objectMapper.writer().withDefaultPrettyPrinter(); - return writer.writeValueAsString(o); } - private static JsonValue parseJson(final String json) throws Exception { + static JsonValue parseJson(final String json) throws Exception { try (StringReader r = new StringReader(json)) { return new JsonValue(readJsonLenient(r)); } diff --git a/opendj-server-legacy/resource/config/rest2ldap/endpoints/api/example-v1.json b/opendj-server-legacy/resource/config/rest2ldap/endpoints/api/example-v1.json index b5a0b02bc3..096de36f7e 100644 --- a/opendj-server-legacy/resource/config/rest2ldap/endpoints/api/example-v1.json +++ b/opendj-server-legacy/resource/config/rest2ldap/endpoints/api/example-v1.json @@ -21,18 +21,6 @@ "dnAttribute": "uid" } }, - // This resource is the same as "users", but read-only. - // Users cannot be created, modified, or deleted through this sub-resource. - "read-only-users": { - "type": "collection", - "dnTemplate": "ou=people,dc=example,dc=com", - "resource": "frapi:opendj:rest2ldap:user:1.0", - "namingStrategy": { - "type": "clientDnNaming", - "dnAttribute": "uid" - }, - "isReadOnly": true - }, "groups": { "type": "collection", "dnTemplate": "ou=groups,dc=example,dc=com", diff --git a/opendj-server-legacy/src/main/java/org/opends/server/util/Platform.java b/opendj-server-legacy/src/main/java/org/opends/server/util/Platform.java index ce0c8a211d..e55c24852e 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/util/Platform.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/util/Platform.java @@ -63,7 +63,7 @@ public final class Platform private static final PlatformIMPL IMPL; /** The minimum java supported version. */ - public static final String JAVA_MINIMUM_VERSION_NUMBER = "7.0"; + public static final String JAVA_MINIMUM_VERSION_NUMBER = "8"; static {