21
21
import com .google .gson .Gson ;
22
22
import com .google .gson .GsonBuilder ;
23
23
import com .google .gson .JsonParser ;
24
-
25
- import okhttp3 .OkHttpClient ;
26
- import okhttp3 .Request ;
27
- import okhttp3 .Response ;
28
-
29
24
import java .io .IOException ;
30
- import java .io .PrintWriter ;
31
25
import java .util .Enumeration ;
32
26
import java .util .Map ;
33
27
import java .util .Properties ;
28
+ import java .util .TreeMap ;
34
29
import java .util .concurrent .TimeUnit ;
35
30
import javax .servlet .annotation .WebServlet ;
36
31
import javax .servlet .http .Cookie ;
37
32
import javax .servlet .http .HttpServlet ;
38
33
import javax .servlet .http .HttpServletRequest ;
39
34
import javax .servlet .http .HttpServletResponse ;
35
+ import okhttp3 .OkHttpClient ;
36
+ import okhttp3 .Request ;
37
+ import okhttp3 .Response ;
38
+ import org .thymeleaf .TemplateEngine ;
39
+ import org .thymeleaf .context .WebContext ;
40
+ import org .thymeleaf .templateresolver .ServletContextTemplateResolver ;
40
41
41
42
42
43
// [START example]
46
47
urlPatterns = "/gaeinfo" )
47
48
public class GaeInfoServlet extends HttpServlet {
48
49
49
- final String [] v1 = {
50
+ private final String [] metaPath = {
50
51
"/computeMetadata/v1/project/numeric-project-id" , // (pending)
51
52
"/computeMetadata/v1/project/project-id" ,
52
53
"/computeMetadata/v1/instance/zone" ,
@@ -57,44 +58,30 @@ public class GaeInfoServlet extends HttpServlet {
57
58
// "/computeMetadata/v1/instance/service-accounts/default/token"
58
59
};
59
60
60
- final String [] v1Acct = {
61
+ final String [] metaServiceAcct = {
61
62
"/computeMetadata/v1/instance/service-accounts/{account}/aliases" ,
62
63
"/computeMetadata/v1/instance/service-accounts/{account}/email" ,
63
64
"/computeMetadata/v1/instance/service-accounts/{account}/scopes" ,
64
65
// Tokens work - but are a security risk to display
65
66
// "/computeMetadata/v1/instance/service-accounts/{account}/token"
66
67
};
67
68
68
- final String metadata = "http://metadata.google.internal" ;
69
+ private final String metadata = "http://metadata.google.internal" ;
70
+ private TemplateEngine templateEngine ;
69
71
70
- public final OkHttpClient ok = new OkHttpClient .Builder ()
72
+ // Use OkHttp from Square as it's quite easy to use for simple fetches.
73
+ private final OkHttpClient ok = new OkHttpClient .Builder ()
71
74
.readTimeout (500 , TimeUnit .MILLISECONDS ) // Don't dawdle
72
75
.writeTimeout (500 , TimeUnit .MILLISECONDS )
73
76
.build ();
74
77
75
- public Gson gson = new GsonBuilder ()
78
+ // Setup to pretty print returned json
79
+ private final Gson gson = new GsonBuilder ()
76
80
.setPrettyPrinting ()
77
81
.create ();
78
- public JsonParser jp = new JsonParser ();
79
-
80
- StringBuilder table (String title , String c ) {
81
- StringBuilder sb = new StringBuilder ();
82
- sb .append ("<h3>" );
83
- sb .append (title );
84
- sb .append ("</h3><table>" );
85
- sb .append (c );
86
- sb .append ("</table>" );
87
- return sb ;
88
- }
89
-
90
- String tr (String c ) {
91
- return "<tr>" + c + "</tr>" ;
92
- }
93
-
94
- String td (String s ) {
95
- return "<td>" + s + "</td>" ;
96
- }
82
+ private final JsonParser jp = new JsonParser ();
97
83
84
+ // Fetch Metadata
98
85
String fetchMetadata (String key ) throws IOException {
99
86
Request request = new Request .Builder ()
100
87
.url (metadata + key )
@@ -106,122 +93,126 @@ String fetchMetadata(String key) throws IOException {
106
93
return response .body ().string ();
107
94
}
108
95
109
- String recursMetadata (String prefix ) throws IOException {
96
+ String fetchJsonMetadata (String prefix ) throws IOException {
110
97
Request request = new Request .Builder ()
111
- .url (metadata + prefix + "?recursive=true" )
98
+ .url (metadata + prefix )
112
99
.addHeader ("Metadata-Flavor" , "Google" )
113
100
.get ()
114
101
.build ();
115
102
116
103
Response response = ok .newCall (request ).execute ();
117
104
105
+ // Convert json to prety json
118
106
return gson .toJson (jp .parse (response .body ().string ()));
119
107
}
120
108
121
-
122
109
@ Override
123
- public void doGet (HttpServletRequest req , HttpServletResponse resp ) throws IOException {
124
- resp .setContentType ("text/html" );
125
- PrintWriter p = resp .getWriter ();
126
- StringBuilder sb = new StringBuilder (4096 );
110
+ public void init () {
111
+ // Setup ThymeLeaf
112
+ ServletContextTemplateResolver templateResolver =
113
+ new ServletContextTemplateResolver (this .getServletContext ());
114
+
115
+ templateResolver .setPrefix ("/WEB-INF/templates/" );
116
+ templateResolver .setSuffix (".html" );
117
+ templateResolver .setCacheTTLMs (Long .valueOf (1200000L )); // TTL=20m
127
118
128
- p .print ("<html><body>" );
119
+ // Cache is set to true by default. Set to false if you want templates to
120
+ // be automatically updated when modified.
121
+ templateResolver .setCacheable (true );
122
+
123
+ templateEngine = new TemplateEngine ();
124
+ templateEngine .setTemplateResolver (templateResolver );
125
+ }
129
126
127
+
128
+ @ Override
129
+ public void doGet (HttpServletRequest req , HttpServletResponse resp ) throws IOException {
130
+ String key ="" ;
130
131
final AppIdentityService appIdentity = AppIdentityServiceFactory .getAppIdentityService ();
132
+ WebContext ctx = new WebContext (req , resp , getServletContext (), req .getLocale ());
131
133
132
- sb .append (table ("AppIdentity" ,
133
- tr (td ("ServiceAccountName" ) + td (appIdentity .getServiceAccountName ()))
134
- + tr (td ("GCS Bucket" ) + td (appIdentity .getDefaultGcsBucketName ()))
135
- ));
134
+ resp .setContentType ("text/html" );
135
+
136
+ ctx .setVariable ("production" , SystemProperty .environment .value ().name ());
137
+ ctx .setVariable ("ServiceAccountName" , appIdentity .getServiceAccountName ());
138
+ ctx .setVariable ("gcs" , appIdentity .getDefaultGcsBucketName ());
136
139
137
- sb .append (table ("SystemProperties" ,
138
- tr (td ("appId" ) + td (SystemProperty .applicationId .get ()))
139
- + tr (td ("appVer" ) + td (SystemProperty .applicationVersion .get ()))
140
- + tr (td ("version" ) + td (SystemProperty .version .get ()))
141
- + tr (td ("environment" ) + td (SystemProperty .environment .get ()))
142
- ));
140
+ ctx .setVariable ("appId" , SystemProperty .applicationId .get ());
141
+ ctx .setVariable ("appVer" , SystemProperty .applicationVersion .get ());
142
+ ctx .setVariable ("version" , SystemProperty .version .get ());
143
+ ctx .setVariable ("environment" , SystemProperty .environment .get ());
143
144
144
145
// Environment Atributes
145
146
ApiProxy .Environment env = ApiProxy .getCurrentEnvironment ();
146
147
Map <String , Object > attr = env .getAttributes ();
148
+ TreeMap <String , String > m = new TreeMap <>();
147
149
148
- StringBuilder c = new StringBuilder (1024 );
149
- for (String key : attr .keySet ()) {
150
- Object o = attr .get (key );
150
+ for (String k : attr .keySet ()) {
151
+ Object o = attr .get (k );
151
152
152
153
if (o .getClass ().getCanonicalName ().equals ("java.lang.String" )) {
153
- c .append (tr (td (key ) + td ((String ) o )));
154
+ m .put (k , (String ) o );
155
+ } else if (o .getClass ().getCanonicalName ().equals ("java.lang.Boolean" )) {
156
+ m .put (k , ((Boolean ) o ).toString ());
154
157
} else {
155
- c . append ( tr ( td ( key ) + td ( o .getClass ().getCanonicalName ()) ));
158
+ m . put ( k , "a " + o .getClass ().getCanonicalName ());
156
159
}
157
160
}
158
- sb . append ( table ( "Environment Attributes " , c . toString ()) );
161
+ ctx . setVariable ( "attribs " , m );
159
162
160
- c = new StringBuilder ( 1024 );
163
+ m = new TreeMap <>( );
161
164
for (Enumeration <String > e = req .getHeaderNames (); e .hasMoreElements (); ) {
162
- String key = e .nextElement ();
163
- String val = req .getHeader (key );
164
- c .append (tr (td (key ) + td (val )));
165
+ key = e .nextElement ();
166
+ m .put (key , req .getHeader (key ));
165
167
}
166
- sb . append ( table ( "Headers " , c . toString ()) );
168
+ ctx . setVariable ( "headers " , m );
167
169
168
170
Cookie [] cookies = req .getCookies ();
171
+ m = new TreeMap <>();
169
172
if (cookies != null && cookies .length != 0 ) {
170
- c = new StringBuilder ();
171
173
for (Cookie co : cookies ) {
172
- c .append (tr (td (co .getName ()) + td (co .getValue ()) + td (co .getComment ())
173
- + td (co .getPath ()) + td (Integer .toString (co .getMaxAge ()))));
174
+ m .put (co .getName (), co .getValue ());
174
175
}
175
- sb .append (table ("Cookies" , c .toString ()));
176
176
}
177
+ ctx .setVariable ("cookies" , m );
177
178
178
179
Properties properties = System .getProperties ();
179
- c = new StringBuilder ( 1024 );
180
+ m = new TreeMap <>( );
180
181
for (Enumeration e = properties .propertyNames (); e .hasMoreElements (); ) {
181
- String key = (String ) e .nextElement ();
182
- c . append ( tr ( td ( key ) + td (( String ) properties .get (key )) ));
182
+ key = (String ) e .nextElement ();
183
+ m . put ( key , ( String ) properties .get (key ));
183
184
}
184
- sb . append ( table ( "Java SystemProperties " , c . toString ()) );
185
+ ctx . setVariable ( "systemprops " , m );
185
186
186
187
Map <String , String > envVar = System .getenv ();
187
- c = new StringBuilder (1024 );
188
- for (String key : envVar .keySet ()) {
189
- c .append (tr (td (key ) + td (envVar .get (key ))));
190
- }
191
- sb .append (table ("Envirionment Variables" , c .toString ()));
188
+ m = new TreeMap <>(envVar );
189
+ ctx .setVariable ("envvar" , m );
192
190
191
+ // The metadata server is only on a production system
193
192
if (SystemProperty .environment .value () == SystemProperty .Environment .Value .Production ) {
194
- c = new StringBuilder (1024 );
195
- for (String key : v1 ) {
196
- String val = fetchMetadata (key );
197
- if (val != null ) {
198
- c .append (tr (td (key ) + td (val )));
199
- }
193
+
194
+ m = new TreeMap <>();
195
+ for (String k : metaPath ) {
196
+ m .put (k , fetchMetadata (key ));
200
197
}
201
- sb .append (table ("Metadata" , c .toString ()));
202
-
203
- c = new StringBuilder (1024 );
204
- for (String key : v1Acct ) {
205
- key = key .replace ("{account}" , appIdentity .getServiceAccountName ());
206
- String val = fetchMetadata (key );
207
- if (val != null ) {
208
- c .append (tr (td (key ) + td (val )));
209
- }
198
+ ctx .setVariable ("Metadata" , m .descendingMap ());
199
+
200
+ m = new TreeMap <>();
201
+ for (String k : metaServiceAcct ) {
202
+ // substitute a service account for {account}
203
+ k = k .replace ("{account}" , appIdentity .getServiceAccountName ());
204
+ m .put (k , fetchMetadata (k ));
210
205
}
211
- sb .append (table ("ServiceAccount Metadata" , c .toString ()));
212
-
213
- sb .append ("<h3>Recursive service-accounts</h3><pre><code>"
214
- + recursMetadata ("/computeMetadata/v1/instance/service-accounts/" )
215
- + "</code></pre>" );
216
- sb .append ("<h3>Recursive all metadata</h3><pre><code>"
217
- + recursMetadata ("/" )
218
- + "</code></pre>" );
219
- }
206
+ ctx .setVariable ("sam" , m .descendingMap ());
220
207
221
- sb .append ("</body></html>" );
222
- p .append (sb );
223
- p .close ();
208
+ // Recursivly get all info about service accounts -- Note tokens are leftout by default.
209
+ ctx .setVariable ("rsa" ,
210
+ fetchJsonMetadata ("/computeMetadata/v1/instance/service-accounts/?recursive=true" ));
211
+ // Recursivly get all data on Metadata server.
212
+ ctx .setVariable ("ram" , fetchJsonMetadata ("/?recursive=true" ));
213
+ }
224
214
215
+ templateEngine .process ("index" , ctx , resp .getWriter ());
225
216
}
226
217
}
227
218
// [END example]
0 commit comments