1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * See LICENSE.txt included in this distribution for the specific 9 * language governing permissions and limitations under the License. 10 * 11 * When distributing Covered Code, include this CDDL HEADER in each 12 * file and include the License file at LICENSE.txt. 13 * If applicable, add the following below this CDDL HEADER, with the 14 * fields enclosed by brackets "[]" replaced with your own identifying 15 * information: Portions Copyright [yyyy] [name of copyright owner] 16 * 17 * CDDL HEADER END 18 */ 19 20 /* 21 * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. 22 * Portions Copyright (c) 2017, 2020, Chris Fraire <cfraire@me.com>. 23 */ 24 package org.opengrok.web.api.v1.controller; 25 26 import jakarta.inject.Inject; 27 import jakarta.servlet.http.HttpServletRequest; 28 import jakarta.ws.rs.Consumes; 29 import jakarta.ws.rs.GET; 30 import jakarta.ws.rs.POST; 31 import jakarta.ws.rs.PUT; 32 import jakarta.ws.rs.Path; 33 import jakarta.ws.rs.PathParam; 34 import jakarta.ws.rs.Produces; 35 import jakarta.ws.rs.QueryParam; 36 import jakarta.ws.rs.WebApplicationException; 37 import jakarta.ws.rs.core.Context; 38 import jakarta.ws.rs.core.MediaType; 39 import jakarta.ws.rs.core.Response; 40 import org.opengrok.indexer.configuration.CommandTimeoutType; 41 import org.opengrok.indexer.configuration.RuntimeEnvironment; 42 import org.opengrok.indexer.util.ClassUtil; 43 import org.opengrok.web.api.ApiTask; 44 import org.opengrok.web.api.ApiTaskManager; 45 import org.opengrok.web.api.v1.suggester.provider.service.SuggesterService; 46 47 import java.io.IOException; 48 import java.io.InputStream; 49 import java.nio.charset.StandardCharsets; 50 51 import static org.opengrok.web.api.v1.controller.ConfigurationController.PATH; 52 53 @Path(PATH) 54 public class ConfigurationController { 55 56 private final RuntimeEnvironment env = RuntimeEnvironment.getInstance(); 57 58 public static final String PATH = "/configuration"; 59 60 @Inject 61 private SuggesterService suggesterService; 62 63 @GET 64 @Produces(MediaType.APPLICATION_XML) get()65 public String get() { 66 return env.getConfigurationXML(); 67 } 68 69 @PUT 70 @Consumes(MediaType.APPLICATION_XML) set(@ontext HttpServletRequest request, @QueryParam("reindex") final boolean reindex)71 public Response set(@Context HttpServletRequest request, 72 @QueryParam("reindex") final boolean reindex) throws IOException { 73 74 String body; 75 try (InputStream inputStream = request.getInputStream()) { 76 body = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); 77 } 78 79 return ApiTaskManager.getInstance().submitApiTask(PATH, 80 new ApiTask(request.getRequestURI(), () -> { 81 env.applyConfig(body, reindex, CommandTimeoutType.RESTFUL); 82 suggesterService.refresh(); 83 return null; 84 })); 85 } 86 87 @GET 88 @Path("/{field}") 89 @Produces(MediaType.APPLICATION_JSON) getField(@athParam"field") final String field)90 public Object getField(@PathParam("field") final String field) { 91 return getConfigurationValueException(field); 92 } 93 94 @PUT 95 @Path("/{field}") setField(@ontext HttpServletRequest request, @PathParam("field") final String field, final String value)96 public Response setField(@Context HttpServletRequest request, 97 @PathParam("field") final String field, final String value) { 98 99 setConfigurationValueException(field, value); 100 101 return ApiTaskManager.getInstance().submitApiTask(PATH, 102 new ApiTask(request.getRequestURI(), () -> { 103 // apply the configuration - let the environment reload the configuration if necessary 104 env.applyConfig(false, CommandTimeoutType.RESTFUL); 105 suggesterService.refresh(); 106 return null; 107 })); 108 } 109 110 @POST 111 @Path("/authorization/reload") 112 public Response reloadAuthorization(@Context HttpServletRequest request) { 113 return ApiTaskManager.getInstance().submitApiTask("authorization", 114 new ApiTask(request.getRequestURI(), 115 () -> { 116 env.getAuthorizationFramework().reload(); 117 return null; 118 }, 119 Response.Status.NO_CONTENT)); 120 } 121 122 private Object getConfigurationValueException(String fieldName) throws WebApplicationException { 123 final IOException[] capture = new IOException[1]; 124 final int IOE_INDEX = 0; 125 Object result = env.syncReadConfiguration(configuration -> { 126 try { 127 return ClassUtil.getFieldValue(configuration, fieldName); 128 } catch (IOException ex) { 129 capture[IOE_INDEX] = ex; 130 return null; 131 } 132 }); 133 if (capture[IOE_INDEX] != null) { 134 throw new WebApplicationException(capture[IOE_INDEX], Response.Status.BAD_REQUEST); 135 } 136 return result; 137 } 138 139 private void setConfigurationValueException(String fieldName, String value) 140 throws WebApplicationException { 141 142 final IOException[] capture = new IOException[1]; 143 final int IOE_INDEX = 0; 144 env.syncWriteConfiguration(value, (configuration, v) -> { 145 try { 146 ClassUtil.setFieldValue(configuration, fieldName, v); 147 } catch (IOException ex) { 148 capture[IOE_INDEX] = ex; 149 } 150 }); 151 if (capture[IOE_INDEX] != null) { 152 throw new WebApplicationException(capture[IOE_INDEX], Response.Status.BAD_REQUEST); 153 } 154 } 155 } 156