001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.microservice.resources; 014 015import static org.apache.juneau.dto.html5.HtmlBuilder.*; 016import static org.apache.juneau.http.HttpMethodName.*; 017 018import java.io.*; 019import java.util.Map; 020 021import org.apache.juneau.*; 022import org.apache.juneau.dto.html5.*; 023import org.apache.juneau.http.annotation.*; 024import org.apache.juneau.http.annotation.Body; 025import org.apache.juneau.parser.*; 026import org.apache.juneau.rest.*; 027import org.apache.juneau.rest.annotation.*; 028import org.apache.juneau.rest.exception.*; 029 030/** 031 * Shows contents of the microservice configuration file. 032 */ 033@RestResource( 034 path="/config", 035 title="Configuration", 036 description="Contents of configuration file.", 037 htmldoc=@HtmlDoc( 038 navlinks={ 039 "up: request:/..", 040 "options: servlet:/?method=OPTIONS", 041 "edit: servlet:/edit" 042 } 043 ) 044) 045@SuppressWarnings("javadoc") 046public class ConfigResource extends BasicRestServlet { 047 private static final long serialVersionUID = 1L; 048 049 @RestMethod( 050 name=GET, 051 path="/", 052 summary="Get config file contents", 053 description="Show contents of config file as an ObjectMap.", 054 swagger=@MethodSwagger( 055 responses={ 056 "200:{ description:'Config file as a map of map of objects.', 'x-example':{'':{defaultKey:'defaultValue'},'Section1':{key1:'val1',key2:123}}}" 057 } 058 ) 059 ) 060 public ObjectMap getConfig() { 061 return getServletConfig().getConfig().asMap(); 062 } 063 064 @RestMethod( 065 name=GET, 066 path="/edit", 067 summary="Render form entry page for editing config file", 068 description="Renders a form entry page for editing the raw text of a config file." 069 ) 070 public Form getConfigEditForm() { 071 return form().id("form").action("servlet:/").method("POST").enctype("application/x-www-form-urlencoded").children( 072 div()._class("data").children( 073 table( 074 tr(td().style("text-align:right").children(button("submit","Submit"),button("reset","Reset"))), 075 tr(th().child("Contents")), 076 tr(th().child( 077 textarea().name("contents").rows(40).cols(120).style("white-space:pre;word-wrap:normal;overflow-x:scroll;font-family:monospace;") 078 .text(getServletConfig().getConfig().toString())) 079 ) 080 ) 081 ) 082 ); 083 } 084 085 @RestMethod( 086 name=GET, 087 path="/{section}", 088 summary="Get config file section contents", 089 description="Show contents of config file section as an ObjectMap.", 090 swagger=@MethodSwagger( 091 responses={ 092 "200:{ description:'Config file section as a map of objects.', 'x-example':{key1:'val1',key2:123}}" 093 } 094 ) 095 ) 096 public ObjectMap getConfigSection( 097 @Path(name="section", description="Section name in config file.", example="REST") String section 098 ) throws SectionNotFound, BadConfig { 099 100 return getSection(section); 101 } 102 103 @RestMethod( 104 name=GET, 105 path="/{section}/{key}", 106 summary="Get config file entry value", 107 description="Show value of config file entry as a simple string.", 108 swagger=@MethodSwagger( 109 responses={ 110 "200:{ description:'Entry value.', 'x-example':'servlet:/htdocs/themes/dark.css'}" 111 } 112 ) 113 ) 114 public String getConfigEntry( 115 @Path(name="section", description="Section name in config file.", example="REST") String section, 116 @Path(name="key", description="Key name in section.", example="theme") String key 117 ) throws SectionNotFound, BadConfig { 118 119 return getSection(section).getString(key); 120 } 121 122 @RestMethod( 123 name=POST, 124 path="/", 125 summary="Update config file contents", 126 description="Update the contents of the config file from a FORM post.", 127 swagger=@MethodSwagger( 128 responses={ 129 "200:{ description:'Config file section as a map of objects.', 'x-example':{key1:'val1',key2:123}}" 130 } 131 ) 132 ) 133 public ObjectMap setConfigContentsFormPost( 134 @FormData(name="contents", description="New contents in INI file format.") String contents 135 ) throws Exception { 136 137 return setConfigContents(new StringReader(contents)); 138 } 139 140 @RestMethod( 141 name=PUT, 142 path="/", 143 summary="Update config file contents", 144 description="Update the contents of the config file from raw text.", 145 swagger=@MethodSwagger( 146 responses={ 147 "200:{ description:'Config file section as a map of objects.', 'x-example':{key1:'val1',key2:123}}" 148 } 149 ) 150 ) 151 public ObjectMap setConfigContents( 152 @Body(description="New contents in INI file format.") Reader contents 153 ) throws Exception { 154 155 return getServletConfig().getConfig().load(contents, true).asMap(); 156 } 157 158 @RestMethod( 159 name=PUT, 160 path="/{section}", 161 summary="Update config section contents", 162 description="Add or overwrite a config file section.", 163 swagger=@MethodSwagger( 164 responses={ 165 "200:{ description:'Config file section as a map of objects.', 'x-example':{key1:'val1',key2:123}}" 166 } 167 ) 168 ) 169 public ObjectMap setConfigSection( 170 @Path(name="section", description="Section name in config file.", example="REST") String section, 171 @Body( 172 description="New contents of config section as a simple map of key/value pairs.", 173 example="{theme:'servlet:/htdocs/themes/dark.css'}" 174 ) Map<String,Object> contents 175 ) throws Exception { 176 177 getServletConfig().getConfig().setSection(section, null, contents); 178 return getSection(section); 179 } 180 181 @RestMethod( 182 name=PUT, 183 path="/{section}/{key}", 184 summary="Update config entry value", 185 description="Add or overwrite a config file entry.", 186 swagger=@MethodSwagger( 187 responses={ 188 "200:{ description:'The updated value.', 'x-example':'servlet:/htdocs/themes/dark.css'}" 189 } 190 ) 191 ) 192 public String setConfigValue( 193 @Path(name="section", description="Section name in config file.", example="REST") String section, 194 @Path(name="key", description="Key name in section.", example="theme") String key, 195 @Body(description="New value for entry.", example="servlet:/htdocs/themes/dark.css") String value 196 ) throws SectionNotFound, BadConfig { 197 198 getServletConfig().getConfig().set(section + '/' + key, value); 199 return getSection(section).getString(key); 200 } 201 202 //----------------------------------------------------------------------------------------------------------------- 203 // Helper beans 204 //----------------------------------------------------------------------------------------------------------------- 205 206 @Response(description="Section not found.") 207 private class SectionNotFound extends NotFound { 208 private static final long serialVersionUID = 1L; 209 210 SectionNotFound() { 211 super("Section not found."); 212 } 213 } 214 215 @Response(description="The configuration file contained syntax errors and could not be parsed.") 216 private class BadConfig extends InternalServerError { 217 private static final long serialVersionUID = 1L; 218 219 BadConfig(Exception e) { 220 super(e, "The configuration file contained syntax errors and could not be parsed."); 221 } 222 } 223 224 //----------------------------------------------------------------------------------------------------------------- 225 // Helper methods 226 //----------------------------------------------------------------------------------------------------------------- 227 228 private ObjectMap getSection(String name) throws SectionNotFound, BadConfig { 229 ObjectMap m; 230 try { 231 m = getServletConfig().getConfig().getSectionAsMap(name); 232 } catch (ParseException e) { 233 throw new BadConfig(e); 234 } 235 if (m == null) 236 throw new SectionNotFound(); 237 return m; 238 } 239}