1 // Copyright 2008 Google Inc. All Rights Reserved.
2 package com
.google
.apphosting
.utils
.config
;
5 import java
.io
.FileInputStream
;
6 import java
.io
.FileNotFoundException
;
7 import java
.io
.IOException
;
8 import java
.io
.InputStream
;
9 import java
.util
.logging
.Level
;
10 import java
.util
.logging
.Logger
;
13 * Creates an {@link AppEngineWebXml} instance from
14 * <appdir>WEB-INF/appengine-web.xml. If you want to read the configuration
15 * from something that isn't a file, subclass and override
16 * {@link #getInputStream()}.
19 public class AppEngineWebXmlReader
{
20 private static final Logger logger
=
21 Logger
.getLogger(AppEngineWebXmlReader
.class.getName());
23 private static final String CONCURRENT_REQUESTS_URL
=
24 "http://code.google.com/appengine/docs/java/config/appconfig.html#Using_Concurrent_Requests";
26 private static final String DATASTORE_AUTO_IDS_URL
=
27 "http://developers.google.com/appengine/docs/java/datastore/entities#Kinds_and_Identifiers";
29 private static final String APPCFG_AUTO_IDS_URL
=
30 "http://developers.google.com/appengine/docs/java/config/appconfig#auto_id_policy";
32 public static final String DEFAULT_RELATIVE_FILENAME
= "WEB-INF/appengine-web.xml";
34 private final String filename
;
37 * Creates a reader for appengine-web.xml.
39 * @param appDir The directory in which the config file resides.
40 * @param relativeFilename The path to the config file, relative to
43 public AppEngineWebXmlReader(String appDir
, String relativeFilename
) {
44 if (appDir
.length() > 0 && appDir
.charAt(appDir
.length() - 1) != File
.separatorChar
) {
45 appDir
+= File
.separatorChar
;
47 this.filename
= appDir
+ relativeFilename
;
51 * Creates a reader for appengine-web.xml.
53 * @param appDir The directory in which the config file resides. The
54 * path to the config file relative to the directory is assumed to be
55 * {@link #DEFAULT_RELATIVE_FILENAME}.
57 public AppEngineWebXmlReader(String appDir
) {
58 this(appDir
, DEFAULT_RELATIVE_FILENAME
);
62 * @return A {@link AppEngineWebXml} config object derived from the
63 * contents of <appdir>WEB-INF/appengine-web.xml.
65 * @throws AppEngineConfigException If <appdir>WEB-INF/appengine-web.xml does
66 * not exist. Also thrown if we are unable to parse the xml.
68 public AppEngineWebXml
readAppEngineWebXml() {
69 InputStream is
= null;
70 AppEngineWebXml appEngineWebXml
;
72 is
= getInputStream();
73 appEngineWebXml
= processXml(is
);
74 logger
.info("Successfully processed " + getFilename());
75 if (!appEngineWebXml
.getThreadsafeValueProvided()) {
76 if (allowMissingThreadsafeElement()) {
77 logger
.warning("appengine-web.xml does not contain a <threadsafe> element. This will "
78 + "be treated as an error the next time you deploy.\nSee " + CONCURRENT_REQUESTS_URL
79 + " for more information.\nYou probably want to enable concurrent requests.");
81 throw new AppEngineConfigException("appengine-web.xml does not contain a <threadsafe> "
82 + "element.\nSee " + CONCURRENT_REQUESTS_URL
+ " for more information.\nYou probably "
83 + "want to enable concurrent requests.");
86 if ("legacy".equals(appEngineWebXml
.getAutoIdPolicy())) {
87 logger
.warning("You have set the datastore auto id policy to 'legacy'. It is recommended "
88 + "that you select 'default' instead.\nLegacy auto ids are deprecated. You can "
89 + "continue to allocate legacy ids manually using the allocateIds() API functions.\n"
90 + "For more information see:\n"
91 + APPCFG_AUTO_IDS_URL
+ "\n" + DATASTORE_AUTO_IDS_URL
+ "\n");
93 } catch (Exception e
) {
94 String msg
= "Received exception processing " + getFilename();
95 logger
.log(Level
.SEVERE
, msg
, e
);
96 if (e
instanceof AppEngineConfigException
) {
97 throw (AppEngineConfigException
) e
;
99 throw new AppEngineConfigException(msg
, e
);
103 return appEngineWebXml
;
106 protected boolean allowMissingThreadsafeElement() {
110 public String
getFilename() {
114 private void close(InputStream is
) {
118 } catch (IOException e
) {
119 throw new AppEngineConfigException(e
);
124 protected AppEngineWebXml
processXml(InputStream is
) {
125 return new AppEngineWebXmlProcessor().processXml(is
);
128 protected InputStream
getInputStream() {
130 return new FileInputStream(getFilename());
131 } catch (FileNotFoundException fnfe
) {
132 throw new AppEngineConfigException(
133 "Could not locate " + new File(getFilename()).getAbsolutePath(), fnfe
);