You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2018/01/04 17:06:32 UTC
[4/4] juneau git commit: Improvements to static files support in REST.
Improvements to static files support in REST.
Project: http://git-wip-us.apache.org/repos/asf/juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/juneau/commit/b820b273
Tree: http://git-wip-us.apache.org/repos/asf/juneau/tree/b820b273
Diff: http://git-wip-us.apache.org/repos/asf/juneau/diff/b820b273
Branch: refs/heads/master
Commit: b820b27351b06241b74161765086cc26320f9c53
Parents: 2da728a
Author: JamesBognar <ja...@apache.org>
Authored: Thu Jan 4 12:06:21 2018 -0500
Committer: JamesBognar <ja...@apache.org>
Committed: Thu Jan 4 12:06:21 2018 -0500
----------------------------------------------------------------------
.../apache/juneau/utils/StringUtilsTest.java | 31 +-
juneau-core/juneau-marshall/TODO.txt | 3 +-
.../org/apache/juneau/internal/ClassUtils.java | 22 +-
.../org/apache/juneau/internal/StringUtils.java | 16 +-
.../juneau/utils/ClasspathResourceFinder.java | 62 ++
.../utils/ClasspathResourceFinderBasic.java | 60 ++
.../utils/ClasspathResourceFinderRecursive.java | 33 +
.../utils/ClasspathResourceFinderSimple.java | 144 +++
.../juneau/utils/ClasspathResourceManager.java | 211 +++++
.../org/apache/juneau/utils/ResourceFinder.java | 306 -------
juneau-doc/src/main/javadoc/overview.html | 129 ++-
.../juneau/examples/rest/PetStoreResource.java | 3 +-
.../juneau/rest/test/InheritanceResource.java | 6 +-
.../juneau/rest/test/StaticFilesResource.java | 3 +-
.../juneau/rest/test/xdocs/xdocs/test.txt | 13 -
.../juneau/rest/test/xdocs/xsubdocs/test.txt | 13 +
.../org/apache/juneau/rest/test/xdocs2/test.txt | 13 +
.../juneau/rest/test/StaticFilesTest.java | 46 +-
.../org/apache/juneau/rest/client/RestCall.java | 53 +-
.../java/org/apache/juneau/rest/CallMethod.java | 20 +-
.../org/apache/juneau/rest/RequestFormData.java | 9 +-
.../org/apache/juneau/rest/RequestHeaders.java | 9 +-
.../org/apache/juneau/rest/RequestQuery.java | 9 +-
.../org/apache/juneau/rest/RestContext.java | 618 ++++++++++---
.../apache/juneau/rest/RestContextBuilder.java | 869 +++++++++++++++----
.../apache/juneau/rest/RestInfoProvider.java | 8 +-
.../org/apache/juneau/rest/RestRequest.java | 43 +-
.../org/apache/juneau/rest/RestResponse.java | 5 +-
.../apache/juneau/rest/RestServletDefault.java | 5 +-
.../apache/juneau/rest/StaticFileMapping.java | 122 +++
.../juneau/rest/annotation/RestMethod.java | 164 +++-
.../juneau/rest/annotation/RestResource.java | 498 +++++++++--
.../java/org/apache/juneau/rest/package.html | 8 +-
.../org/apache/juneau/rest/vars/FileVar.java | 8 +-
.../org/apache/juneau/rest/widget/Widget.java | 6 +-
35 files changed, 2787 insertions(+), 781 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
index af1b9ba..1f5d947 100755
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
@@ -510,7 +510,36 @@ public class StringUtilsTest {
assertEquals("2\\", r[1]);
assertEquals("", r[2]);
}
-
+
+ //====================================================================================================
+ // split(String,char,int)
+ //====================================================================================================
+ @Test
+ public void testSplitWithLimit() {
+ String[] r;
+
+ r = split("boo:and:foo", ':', 10);
+ assertObjectEquals("['boo','and','foo']", r);
+
+ r = split("boo:and:foo", ':', 2);
+ assertObjectEquals("['boo','and:foo']", r);
+
+ r = split("boo:and:foo", ':', 1);
+ assertObjectEquals("['boo:and:foo']", r);
+
+ r = split("boo:and:foo", ':', 0);
+ assertObjectEquals("['boo:and:foo']", r);
+
+ r = split("boo:and:foo", ':', -1);
+ assertObjectEquals("['boo:and:foo']", r);
+
+ r = split("boo : and : foo", ':', 10);
+ assertObjectEquals("['boo','and','foo']", r);
+
+ r = split("boo : and : foo", ':', 2);
+ assertObjectEquals("['boo','and : foo']", r);
+ }
+
//====================================================================================================
// nullIfEmpty(String)
//====================================================================================================
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-core/juneau-marshall/TODO.txt
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/TODO.txt b/juneau-core/juneau-marshall/TODO.txt
index 70cfc28..dd66236 100644
--- a/juneau-core/juneau-marshall/TODO.txt
+++ b/juneau-core/juneau-marshall/TODO.txt
@@ -15,4 +15,5 @@ Create tests that ensure serializers don't close output but parsers do close inp
Content tests on examples rest.
REST example showing how to use NLS.
-REST example showing how to customize look-and-feel.
\ No newline at end of file
+REST example showing how to customize look-and-feel.
+Improve efficiency of RestRequest constructor.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
index 594d9d1..aa78c06 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
@@ -833,15 +833,27 @@ public final class ClassUtils {
Class<?> c3 = (Class<?>)c2;
if (c3.isInterface() || isAbstract(c3))
return null;
- Constructor<?> con = findPublicConstructor(c3, fuzzyArgs, args);
+
+ // First look for an exact match.
+ Constructor<?> con = findPublicConstructor(c3, false, args);
if (con != null)
- return (T)con.newInstance(fuzzyArgs ? getMatchingArgs(con, args) : args);
+ return (T)con.newInstance(args);
+
+ // Next look for an exact match including the outer.
if (outer != null) {
- Object[] args2 = new AList<>().append(outer).appendAll(args).toArray();
- con = findPublicConstructor(c3, fuzzyArgs, args2);
+ args = new AList<>().append(outer).appendAll(args).toArray();
+ con = findPublicConstructor(c3, false, args);
if (con != null)
- return (T)con.newInstance(fuzzyArgs ? getMatchingArgs(con, args) : args);
+ return (T)con.newInstance(args);
}
+
+ // Finally use fuzzy matching.
+ if (fuzzyArgs) {
+ con = findPublicConstructor(c3, true, args);
+ if (con != null)
+ return (T)con.newInstance(getMatchingArgs(con, args));
+ }
+
throw new FormattedRuntimeException("Could not instantiate class {0}. Constructor not found.", c.getName());
} catch (Exception e) {
throw new FormattedRuntimeException(e, "Could not instantiate class {0}", c.getName());
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
index 953a677..a808b27 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
@@ -493,6 +493,18 @@ public final class StringUtils {
* @return The tokens, or <jk>null</jk> if the string was null.
*/
public static String[] split(String s, char c) {
+ return split(s, c, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Same as {@link #split(String, char)} but limits the number of tokens returned.
+ *
+ * @param s The string to split. Can be <jk>null</jk>.
+ * @param c The character to split on.
+ * @param limit The maximum number of tokens to return.
+ * @return The tokens, or <jk>null</jk> if the string was null.
+ */
+ public static String[] split(String s, char c, int limit) {
char[] unEscapeChars = new char[]{'\\', c};
@@ -506,12 +518,14 @@ public final class StringUtils {
List<String> l = new LinkedList<>();
char[] sArray = s.toCharArray();
int x1 = 0, escapeCount = 0;
- for (int i = 0; i < sArray.length; i++) {
+ limit--;
+ for (int i = 0; i < sArray.length && limit > 0; i++) {
if (sArray[i] == '\\') escapeCount++;
else if (sArray[i]==c && escapeCount % 2 == 0) {
String s2 = new String(sArray, x1, i-x1);
String s3 = unEscapeChars(s2, unEscapeChars);
l.add(s3.trim());
+ limit--;
x1 = i+1;
}
if (sArray[i] != '\\') escapeCount = 0;
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinder.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinder.java
new file mode 100644
index 0000000..39a9601
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinder.java
@@ -0,0 +1,62 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+package org.apache.juneau.utils;
+
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Interface for finding classpath resources.
+ *
+ * <p>
+ * Essentially a wrapper around {@link Class#getResourceAsStream(String)}, but with support for looking up resources
+ * with localized names (e.g. <js>"myfile_ja_JP.txt"</js>).
+ *
+ * <p>
+ * The following predefined implementations are provided:
+ * <ul>
+ * <li>{@link ClasspathResourceFinderSimple} - Simple searching of classpath.
+ * <li>{@link ClasspathResourceFinderBasic} - Same as above, but looks in local JVM working directory if resource
+ * can't be found on classpath.
+ * <li>{@link ClasspathResourceFinderRecursive} - Same as above, except if the resource can't be found on the
+ * classpath relative to the base class, recursively searches up the parent class hierarchy.
+ * </ul>
+ */
+public interface ClasspathResourceFinder {
+
+ /**
+ * Represents "no" classpath resource finder.
+ */
+ public static final class Null implements ClasspathResourceFinder {
+ @Override
+ public InputStream findResource(Class<?> baseClass, String name, Locale locale) throws IOException {
+ throw new NoSuchMethodError();
+ }
+ }
+
+ /**
+ * Returns the contents of the resource with the specified name.
+ *
+ * @param baseClass
+ * The class to use to retrieve the resource.
+ * @param name The resource name.
+ * See {@link Class#getResource(String)} for format.
+ * @param locale
+ * The locale of the resource to retrieve.
+ * Can be <jk>null</jk>.
+ * @return The resolved resource contents, or <jk>null</jk> if the resource was not found.
+ * @throws IOException
+ */
+ InputStream findResource(Class<?> baseClass, String name, Locale locale) throws IOException;
+}
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinderBasic.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinderBasic.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinderBasic.java
new file mode 100644
index 0000000..99114c2
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinderBasic.java
@@ -0,0 +1,60 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+package org.apache.juneau.utils;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Utility class for finding resources for a class.
+ *
+ * <p>
+ * Same as {@link ClasspathResourceFinderSimple}, but if the resource cannot be found in the classpath, then an attempt
+ * is made to look in the JVM working directory.
+ * <br>Path traversals outside the working directory are not allowed for security reasons.
+ */
+public class ClasspathResourceFinderBasic extends ClasspathResourceFinderSimple {
+
+ @Override /* ClasspathResourceFinder */
+ public InputStream findResource(Class<?> baseClass, String name, Locale locale) throws IOException {
+ InputStream is = findClasspathResource(baseClass, name, locale);
+ if (is != null)
+ return is;
+ return findFileSystemResource(name, locale);
+ }
+
+ /**
+ * Workhorse method for retrieving a resource from the file system.
+ *
+ * <p>
+ * This method can be overridden by subclasses to provide customized handling of resource retrieval from file systems.
+ *
+ * @param name The resource name.
+ * @param locale
+ * The resource locale.
+ * <br>Can be <jk>null</jk>.
+ * @return The resource stream, or <jk>null</jk> if it couldn't be found.
+ * @throws IOException
+ */
+ protected InputStream findFileSystemResource(String name, Locale locale) throws IOException {
+ if (name.indexOf("..") == -1) {
+ for (String n2 : getCandidateFileNames(name, locale)) {
+ File f = new File(n2);
+ if (f.exists() && f.canRead() && ! f.isAbsolute()) {
+ return new FileInputStream(f);
+ }
+ }
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinderRecursive.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinderRecursive.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinderRecursive.java
new file mode 100644
index 0000000..b023dcb
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinderRecursive.java
@@ -0,0 +1,33 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+package org.apache.juneau.utils;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Same as {@link ClasspathResourceFinderBasic} but searches for resources up the parent class hierarchy chain.
+ */
+public class ClasspathResourceFinderRecursive extends ClasspathResourceFinderBasic {
+
+ @Override /* ResourceFinder2 */
+ public InputStream findResource(Class<?> baseClass, String name, Locale locale) throws IOException {
+ while (baseClass != null) {
+ InputStream is = findClasspathResource(baseClass, name, locale);
+ if (is != null)
+ return is;
+ baseClass = baseClass.getSuperclass();
+ }
+ return findFileSystemResource(name, locale);
+ }
+}
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinderSimple.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinderSimple.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinderSimple.java
new file mode 100644
index 0000000..bdec620
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceFinderSimple.java
@@ -0,0 +1,144 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+package org.apache.juneau.utils;
+
+import static org.apache.juneau.internal.FileUtils.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.ResourceBundle.*;
+
+/**
+ * Utility class for finding resources for a class.
+ *
+ * <p>
+ * Same as {@link Class#getResourceAsStream(String)} except looks for resources with localized file names.
+ *
+ * <p>
+ * If the <code>locale</code> is specified, then we look for resources whose name matches that locale.
+ * For example, if looking for the resource <js>"MyResource.txt"</js> for the Japanese locale, we will look for
+ * files in the following order:
+ * <ol>
+ * <li><js>"MyResource_ja_JP.txt"</js>
+ * <li><js>"MyResource_ja.txt"</js>
+ * <li><js>"MyResource.txt"</js>
+ * </ol>
+ */
+public class ClasspathResourceFinderSimple implements ClasspathResourceFinder {
+
+ private static final ResourceBundle.Control RB_CONTROL = ResourceBundle.Control.getControl(Control.FORMAT_DEFAULT);
+ private static final List<Locale> ROOT_LOCALE = Arrays.asList(Locale.ROOT);
+
+
+ @Override /* ClasspathResourceFinder */
+ public InputStream findResource(Class<?> baseClass, String name, Locale locale) throws IOException {
+ return findClasspathResource(baseClass, name, locale);
+ }
+
+ /**
+ * Workhorse method for retrieving a resource from the classpath.
+ *
+ * <p>
+ * This method can be overridden by subclasses to provide customized handling of resource retrieval from the classpath.
+ *
+ * @param baseClass The base class providing the classloader.
+ * @param name The resource name.
+ * @param locale
+ * The resource locale.
+ * <br>Can be <jk>null</jk>.
+ * @return The resource stream, or <jk>null</jk> if it couldn't be found.
+ * @throws IOException
+ */
+ protected InputStream findClasspathResource(Class<?> baseClass, String name, Locale locale) throws IOException {
+ if (locale == null)
+ return baseClass.getResourceAsStream(name);
+ for (String n : getCandidateFileNames(name, locale)) {
+ InputStream is = baseClass.getResourceAsStream(n);
+ if (is != null)
+ return is;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the candidate file names for the specified file name in the specified locale.
+ *
+ * <p>
+ * For example, if looking for the <js>"MyResource.txt"</js> file in the Japanese locale, the iterator will return
+ * names in the following order:
+ * <ol>
+ * <li><js>"MyResource_ja_JP.txt"</js>
+ * <li><js>"MyResource_ja.txt"</js>
+ * <li><js>"MyResource.txt"</js>
+ * </ol>
+ *
+ * <p>
+ * If the locale is <jk>null</jk>, then it will only return <js>"MyResource.txt"</js>.
+ *
+ * @param fileName The name of the file to get candidate file names on.
+ * @param l The locale.
+ * @return An iterator of file names to look at.
+ */
+ protected static Iterable<String> getCandidateFileNames(final String fileName, final Locale l) {
+ return new Iterable<String>() {
+ @Override
+ public Iterator<String> iterator() {
+ return new Iterator<String>() {
+ final Iterator<Locale> locales = getCandidateLocales(l).iterator();
+ String baseName, ext;
+
+ @Override
+ public boolean hasNext() {
+ return locales.hasNext();
+ }
+
+ @Override
+ public String next() {
+ Locale l2 = locales.next();
+ if (l2.toString().isEmpty())
+ return fileName;
+ if (baseName == null)
+ baseName = getBaseName(fileName);
+ if (ext == null)
+ ext = getExtension(fileName);
+ return baseName + "_" + l2.toString() + (ext.isEmpty() ? "" : ('.' + ext));
+ }
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ };
+ }
+
+ /**
+ * Returns the candidate locales for the specified locale.
+ *
+ * <p>
+ * For example, if <code>locale</code> is <js>"ja_JP"</js>, then this method will return:
+ * <ol>
+ * <li><js>"ja_JP"</js>
+ * <li><js>"ja"</js>
+ * <li><js>""</js>
+ * </ol>
+ *
+ * @param locale The locale to get the list of candidate locales for.
+ * @return The list of candidate locales.
+ */
+ static final List<Locale> getCandidateLocales(Locale locale) {
+ if (locale == null)
+ return ROOT_LOCALE;
+ return RB_CONTROL.getCandidateLocales("", locale);
+ }
+}
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceManager.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceManager.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceManager.java
new file mode 100644
index 0000000..4dcb5c7
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ClasspathResourceManager.java
@@ -0,0 +1,211 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+package org.apache.juneau.utils;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Class for retrieving and caching resource files from the classpath.
+ */
+public final class ClasspathResourceManager {
+
+ // Maps resource names+locales to found resources.
+ private final ConcurrentHashMap<ResourceKey,byte[]> byteCache;
+ private final ConcurrentHashMap<ResourceKey,String> stringCache;
+
+ private final Class<?> baseClass;
+ private final ClasspathResourceFinder resourceFinder;
+ private final boolean useCache;
+
+ /**
+ * Constructor.
+ *
+ * @param baseClass The default class to use for retrieving resources from the classpath.
+ * @param resourceFinder The resource finder implementation.
+ * @param useCache If <jk>true</jk>, retrieved resources are stored in an in-memory cache for fast lookup.
+ */
+ public ClasspathResourceManager(Class<?> baseClass, ClasspathResourceFinder resourceFinder, boolean useCache) {
+ this.baseClass = baseClass;
+ this.resourceFinder = resourceFinder;
+ this.useCache = useCache;
+ this.byteCache = useCache ? new ConcurrentHashMap<ResourceKey,byte[]>() : null;
+ this.stringCache = useCache ? new ConcurrentHashMap<ResourceKey,String>() : null;
+ }
+
+ /**
+ * Constructor.
+ *
+ * <p>
+ * Uses default {@link ClasspathResourceFinderBasic} for finding resources.
+ *
+ * @param baseClass The default class to use for retrieving resources from the classpath.
+ */
+ public ClasspathResourceManager(Class<?> baseClass) {
+ this(baseClass, new ClasspathResourceFinderBasic(), false);
+ }
+
+ /**
+ * Finds the resource with the given name.
+ *
+ * @param name Name of the desired resource.
+ * @return An input stream to the object, or <jk>null</jk> if the resource could not be found.
+ * @throws IOException
+ */
+ public InputStream getStream(String name) throws IOException {
+ return getStream(name, null);
+ }
+
+ /**
+ * Finds the resource with the given name for the specified locale and returns it as an input stream.
+ *
+ * @param name Name of the desired resource.
+ * @param locale The locale. Can be <jk>null</jk>.
+ * @return An input stream to the object, or <jk>null</jk> if the resource could not be found.
+ * @throws IOException
+ */
+ public InputStream getStream(String name, Locale locale) throws IOException {
+ return getStream(baseClass, name, locale);
+ }
+
+ /**
+ * Finds the resource with the given name for the specified locale and returns it as an input stream.
+ *
+ * @param baseClass
+ * Overrides the default class to use for retrieving the classpath resource.
+ * <br>If <jk>null<jk>, uses the base class passed in through the constructor of this class.
+ * @param name Name of the desired resource.
+ * @param locale The locale. Can be <jk>null</jk>.
+ * @return An input stream to the object, or <jk>null</jk> if the resource could not be found.
+ * @throws IOException
+ */
+ public InputStream getStream(Class<?> baseClass, String name, Locale locale) throws IOException {
+
+ if (baseClass == null)
+ baseClass = this.baseClass;
+
+ if (! useCache)
+ return resourceFinder.findResource(baseClass, name, locale);
+
+ ResourceKey key = new ResourceKey(name, locale);;
+
+ byte[] r = byteCache.get(key);
+ if (r == null) {
+ try (InputStream is = resourceFinder.findResource(baseClass, name, locale)) {
+ if (is != null)
+ byteCache.putIfAbsent(key, IOUtils.readBytes(is, 1024));
+ }
+ }
+
+ r = byteCache.get(key);
+ return r == null ? null : new ByteArrayInputStream(r);
+ }
+
+ /**
+ * Finds the resource with the given name and converts it to a simple string.
+ *
+ * @param name Name of the desired resource.
+ * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found.
+ * @throws IOException
+ */
+ public String getString(String name) throws IOException {
+ return getString(baseClass, name, null);
+ }
+
+ /**
+ * Finds the resource with the given name and converts it to a simple string.
+ *
+ * @param baseClass
+ * Overrides the default class to use for retrieving the classpath resource.
+ * <br>If <jk>null<jk>, uses the base class passed in through the constructor of this class.
+ * @param name Name of the desired resource.
+ * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found.
+ * @throws IOException
+ */
+ public String getString(Class<?> baseClass, String name) throws IOException {
+ return getString(baseClass, name, null);
+ }
+
+ /**
+ * Finds the resource with the given name and converts it to a simple string.
+ *
+ * @param name Name of the desired resource.
+ * @param locale The locale. Can be <jk>null</jk>.
+ * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found.
+ * @throws IOException
+ */
+ public String getString(String name, Locale locale) throws IOException {
+ return getString(baseClass, name, locale);
+ }
+
+ /**
+ * Finds the resource with the given name and converts it to a simple string.
+ *
+ * @param baseClass
+ * Overrides the default class to use for retrieving the classpath resource.
+ * <br>If <jk>null<jk>, uses the base class passed in through the constructor of this class.
+ * @param name Name of the desired resource.
+ * @param locale The locale. Can be <jk>null</jk>.
+ * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found.
+ * @throws IOException
+ */
+ public String getString(Class<?> baseClass, String name, Locale locale) throws IOException {
+
+ if (baseClass == null)
+ baseClass = this.baseClass;
+
+ if (! useCache) {
+ try (InputStream is = resourceFinder.findResource(baseClass, name, locale)) {
+ return IOUtils.read(is, IOUtils.UTF8);
+ }
+ }
+
+ ResourceKey key = new ResourceKey(name, locale);
+
+ String r = stringCache.get(key);
+ if (r == null) {
+ try (InputStream is = resourceFinder.findResource(baseClass, name, locale)) {
+ if (is != null)
+ stringCache.putIfAbsent(key, IOUtils.read(is, IOUtils.UTF8));
+ }
+ }
+
+ return stringCache.get(key);
+ }
+
+ private class ResourceKey {
+ final String name;
+ final Locale locale;
+
+ ResourceKey(String name, Locale locale) {
+ this.name = name;
+ this.locale = locale;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode() + (locale == null ? 0 : locale.hashCode());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null)
+ return false;
+ ResourceKey ok = (ResourceKey)o;
+ return ObjectUtils.equals(name, ok.name) && ObjectUtils.equals(locale, ok.locale);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ResourceFinder.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ResourceFinder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ResourceFinder.java
deleted file mode 100644
index 8205905..0000000
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ResourceFinder.java
+++ /dev/null
@@ -1,306 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
-// * with the License. You may obtain a copy of the License at *
-// * *
-// * http://www.apache.org/licenses/LICENSE-2.0 *
-// * *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
-// * specific language governing permissions and limitations under the License. *
-// ***************************************************************************************************************************
-package org.apache.juneau.utils;
-
-import static org.apache.juneau.internal.FileUtils.*;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.ResourceBundle.*;
-import java.util.concurrent.*;
-
-import org.apache.juneau.internal.*;
-
-/**
- * Utility class for finding resources for a class.
- *
- * <p>
- * Same as {@link Class#getResourceAsStream(String)} except if it doesn't find the resource on this class, it searches
- * up the parent hierarchy chain.
- *
- * <p>
- * If the resource cannot be found in the classpath, then an attempt is made to look in the JVM working directory.
- * <br>Path traversals outside the working directory are not allowed for security reasons.
- *
- * <p>
- * If the <code>locale</code> is specified, then we look for resources whose name matches that locale.
- * For example, if looking for the resource <js>"MyResource.txt"</js> for the Japanese locale, we will look for
- * files in the following order:
- * <ol>
- * <li><js>"MyResource_ja_JP.txt"</js>
- * <li><js>"MyResource_ja.txt"</js>
- * <li><js>"MyResource.txt"</js>
- * </ol>
- *
- * <p>
- * Results are cached for fast lookup.
- */
-public final class ResourceFinder {
-
- private static final ResourceBundle.Control RB_CONTROL = ResourceBundle.Control.getControl(Control.FORMAT_DEFAULT);
- private static final List<Locale> ROOT_LOCALE = Arrays.asList(Locale.ROOT);
-
- // Maps resource names+locales to found resources.
- private final ConcurrentHashMap<ResourceKey,Resource> cache = new ConcurrentHashMap<>();
-
- // Maps resolved URLs to resources.
- private final ConcurrentHashMap<URL,Resource> cacheByUrl = new ConcurrentHashMap<>();
-
- private final Class<?> c;
-
- /**
- * Constructor.
- *
- * @param forClass The class that this resource finder searches against.
- */
- public ResourceFinder(Class<?> forClass) {
- this.c = forClass;
- }
-
- /**
- * Finds the resource with the given name.
- *
- * @param name Name of the desired resource.
- * @return An input stream to the object, or <jk>null</jk> if the resource could not be found.
- * @throws IOException
- */
- public InputStream getResourceAsStream(String name) throws IOException {
- return getResourceAsStream(name, null);
- }
-
- /**
- * Finds the resource with the given name for the specified locale.
- *
- * @param name Name of the desired resource.
- * @param locale The locale. Can be <jk>null</jk>.
- * @return An input stream to the object, or <jk>null</jk> if the resource could not be found.
- * @throws IOException
- */
- public InputStream getResourceAsStream(String name, Locale locale) throws IOException {
- return getResource(name, locale).asInputStream();
- }
-
- /**
- * Finds the resource with the given name and converts it to a simple string.
- *
- * @param name Name of the desired resource.
- * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found.
- * @throws IOException
- */
- public String getResourceAsString(String name) throws IOException {
- return getResourceAsString(name, null);
- }
-
- /**
- * Finds the resource with the given name and converts it to a simple string.
- *
- * @param name Name of the desired resource.
- * @param locale The locale. Can be <jk>null</jk>.
- * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found.
- * @throws IOException
- */
- public String getResourceAsString(String name, Locale locale) throws IOException {
- return getResource(name, locale).asString();
- }
-
-
- //-------------------------------------------------------------------------------------------------------------------
- // Support classes and methods.
- //-------------------------------------------------------------------------------------------------------------------
-
- private static final class ResourceKey {
- final String name;
- final Locale locale;
-
- ResourceKey(String name, Locale locale) {
- this.name = name;
- this.locale = locale;
- }
-
- @Override
- public int hashCode() {
- return name.hashCode() + (locale == null ? 0 : locale.hashCode());
- }
-
- @Override
- public boolean equals(Object o) {
- if (o == null)
- return false;
- ResourceKey ok = (ResourceKey)o;
- return ObjectUtils.equals(name, ok.name) && ObjectUtils.equals(locale, ok.locale);
- }
- }
-
- private static final class Resource {
- private byte[] bytes;
- private String string;
-
- Resource(byte[] bytes) {
- this.bytes = bytes;
- }
-
- String asString() {
- if (bytes == null)
- return null;
- try {
- if (string == null)
- string = new String(bytes, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return string;
- }
-
- InputStream asInputStream() {
- if (bytes == null)
- return null;
- return new ByteArrayInputStream(bytes);
- }
- }
-
- Resource getResource(String name, Locale locale) throws IOException {
- ResourceKey key = new ResourceKey(name, locale);
- Resource r = cache.get(key);
- if (r != null)
- return r;
-
- r = findResource(c, key);
- cache.putIfAbsent(key, r);
- r = cache.get(key);
- return r;
- }
-
- private Resource findResource(Class<?> c2, ResourceKey key) throws IOException {
- while (c2 != null) {
- if (key.locale == null) {
- URL url = c2.getResource(key.name);
- if (url != null) {
- Resource r = cacheByUrl.get(url);
- if (r == null) {
- r = new Resource(IOUtils.readBytes(c2.getResourceAsStream(key.name), 1024));
- cacheByUrl.putIfAbsent(url, r);
- r = cacheByUrl.get(url);
- }
- return r;
- }
- } else {
- for (String n : getCandidateFileNames(key.name, key.locale)) {
- URL url = c2.getResource(n);
- if (url != null) {
- Resource r = cacheByUrl.get(url);
- if (r == null) {
- r = new Resource(IOUtils.readBytes(c2.getResourceAsStream(n), 1024));
- cacheByUrl.putIfAbsent(url, r);
- r = cacheByUrl.get(url);
- }
- return r;
- }
- }
- }
- c2 = c2.getSuperclass();
- }
-
- if (key.name.indexOf("..") == -1) {
- for (String n2 : getCandidateFileNames(key.name, key.locale)) {
- File f = new File(n2);
- if (f.exists() && f.canRead() && ! f.isAbsolute()) {
- URL url = f.toURI().toURL();
- Resource r = cacheByUrl.get(url);
- if (r == null) {
- try (FileInputStream fis = new FileInputStream(f)) {
- r = new Resource(IOUtils.readBytes(fis, 1024));
- }
- cacheByUrl.putIfAbsent(url, r);
- r = cacheByUrl.get(url);
- }
- return r;
- }
- }
- }
-
- return new Resource(null);
- }
-
- /**
- * Returns the candidate file names for the specified file name in the specified locale.
- *
- * <p>
- * For example, if looking for the <js>"MyResource.txt"</js> file in the Japanese locale, the iterator will return
- * names in the following order:
- * <ol>
- * <li><js>"MyResource_ja_JP.txt"</js>
- * <li><js>"MyResource_ja.txt"</js>
- * <li><js>"MyResource.txt"</js>
- * </ol>
- *
- * <p>
- * If the locale is null, then it will only return <js>"MyResource.txt"</js>.
- *
- * @param fileName The name of the file to get candidate file names on.
- * @param l The locale.
- * @return An iterator of file names to look at.
- */
- private static Iterable<String> getCandidateFileNames(final String fileName, final Locale l) {
- return new Iterable<String>() {
- @Override
- public Iterator<String> iterator() {
- return new Iterator<String>() {
- final Iterator<Locale> locales = getCandidateLocales(l).iterator();
- String baseName, ext;
-
- @Override
- public boolean hasNext() {
- return locales.hasNext();
- }
-
- @Override
- public String next() {
- Locale l2 = locales.next();
- if (l2.toString().isEmpty())
- return fileName;
- if (baseName == null)
- baseName = getBaseName(fileName);
- if (ext == null)
- ext = getExtension(fileName);
- return baseName + "_" + l2.toString() + (ext.isEmpty() ? "" : ('.' + ext));
- }
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
- }
- };
- }
-
- /**
- * Returns the candidate locales for the specified locale.
- *
- * <p>
- * For example, if <code>locale</code> is <js>"ja_JP"</js>, then this method will return:
- * <ol>
- * <li><js>"ja_JP"</js>
- * <li><js>"ja"</js>
- * <li><js>""</js>
- * </ol>
- *
- * @param locale The locale to get the list of candidate locales for.
- * @return The list of candidate locales.
- */
- static final List<Locale> getCandidateLocales(Locale locale) {
- if (locale == null)
- return ROOT_LOCALE;
- return RB_CONTROL.getCandidateLocales("", locale);
- }
-}
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-doc/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index 8a09d75..3f56270 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -4924,7 +4924,7 @@
<li>
How to use form entry beans to process form POSTs.
<li>
- How to use the {@link org.apache.juneau.rest.RestRequest#getReaderResource(String)} method to
+ How to use the {@link org.apache.juneau.rest.RestRequest#getClasspathReaderResource(String)} method to
serve up static files with embedded string variables.
</ul>
<p>
@@ -4946,7 +4946,7 @@
<jd>/** GET request handler */</jd>
<ja>@RestMethod</ja>(name=<jsf>GET</jsf>, path=<js>"/"</js>)
<jk>public</jk> ReaderResource doGet(RestRequest req) <jk>throws</jk> IOException {
- <jk>return</jk> req.getReaderResource(<js>"UrlEncodedForm.html"</js>, <jk>true</jk>);
+ <jk>return</jk> req.getClasspathReaderResource(<js>"UrlEncodedForm.html"</js>, <jk>true</jk>);
}
<jd>/** POST request handler */</jd>
@@ -4965,7 +4965,7 @@
}
</p>
<p>
- The {@link org.apache.juneau.rest.RestRequest#getReaderResource(String,boolean)} method pulls in the following
+ The {@link org.apache.juneau.rest.RestRequest#getClasspathReaderResource(String,boolean)} method pulls in the following
file located in the same package as the class:
</p>
@@ -6521,7 +6521,7 @@
*/</jd>
<ja>@RestMethod</ja>(name=<jsf>GET</jsf>, path=<js>"/upload"</js>)
<jk>public</jk> ReaderResource getUploadPage(RestRequest req) <jk>throws</jk> IOException {
- <jk>return</jk> req.getReaderResource(<js>"TempDirUploadPage.html"</js>, <jk>true</jk>);
+ <jk>return</jk> req.getClasspathReaderResource(<js>"TempDirUploadPage.html"</js>, <jk>true</jk>);
}
<jd>/**
@@ -7181,7 +7181,7 @@
<jd>/** GET request handler - Display the query entry page. */</jd>
<ja>@RestMethod</ja>(name=<jsf>GET</jsf>, path=<js>"/"</js>)
<jk>public</jk> ReaderResource doGet(RestRequest req) <jk>throws</jk> IOException {
- <jk>return</jk> req.getReaderResource(<js>"SqlQueryResource.html"</js>, <jk>true</jk>);
+ <jk>return</jk> req.getClasspathReaderResource(<js>"SqlQueryResource.html"</js>, <jk>true</jk>);
}
<jd>/** POST request handler - Execute the query. */</jd>
@@ -7379,7 +7379,7 @@
<jc>// Note that you don't want variables in the config file to be resolved,</jc>
<jc>// so you need to escape any $ characters that you see.</jc>
req.setAttribute(<js>"contents"</js>, getConfig().toString().replaceAll(<js>"\\$"</js>, <js>"\\\\\\$"</js>));
- <jk>return</jk> req.getReaderResource(<js>"ConfigEdit.html"</js>, <jk>true</jk>);
+ <jk>return</jk> req.getClasspathReaderResource(<js>"ConfigEdit.html"</js>, <jk>true</jk>);
}
<jd>/**
@@ -7910,8 +7910,15 @@
</ul>
Code for marshalling of parts have been removed from the URL-Encoding serializers and parsers.
<li>
- <code>ContexBuilder.property(String,Object)</code> renamed to {@link org.apache.juneau.ContextBuilder#set(String,Object)}.
-
+ <code>ContextBuilder.property(String,Object)</code> renamed to {@link org.apache.juneau.ContextBuilder#set(String,Object)}.
+ <li><code>ResourceFinder</code> class has been replaced with the following:
+ <ul>
+ <li>{@link org.apache.juneau.utils.ClasspathResourceFinder}
+ <li>{@link org.apache.juneau.utils.ClasspathResourceFinderSimple}
+ <li>{@link org.apache.juneau.utils.ClasspathResourceFinderBasic}
+ <li>{@link org.apache.juneau.utils.ClasspathResourceFinderRecursive}
+ <li>{@link org.apache.juneau.utils.ClasspathResourceManager}
+ </ul>
</ul>
<h6 class='topic'>juneau-rest-server</h6>
@@ -7959,6 +7966,48 @@
</ul>
<li>
Refactored the <code>RestConfig</code> class into {@link org.apache.juneau.rest.RestContextBuilder}.
+ <br>Settings on {@link org.apache.juneau.rest.RestContext} objects can now be set declaratively through the
+ following new properties:
+ <ul>
+ <li>{@link org.apache.juneau.rest.RestContext#REST_allowHeaderParams REST_allowHeaderParams}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_allowBodyParam REST_allowBodyParam}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_allowedMethodParams REST_allowedMethodParams}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_renderResponseStackTraces REST_renderResponseStackTraces}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_useStackTraceHashes REST_useStackTraceHashes}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_defaultCharset REST_defaultCharset}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_maxInput REST_maxInput}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_paramResolvers REST_paramResolvers}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_converters REST_converters}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_guards REST_guards}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_responseHandlers REST_responseHandlers}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_defaultRequestHeaders REST_defaultRequestHeaders}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_defaultResponseHeaders REST_defaultResponseHeaders}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_supportedAcceptTypes REST_supportedAcceptTypes}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_supportedContentTypes REST_supportedContentTypes}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_clientVersionHeader REST_clientVersionHeader}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_resourceResolver REST_resourceResolver}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_logger REST_logger}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_callHandler REST_callHandler}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_infoProvider REST_infoProvider}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_path REST_path}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_contextPath REST_contextPath}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_staticFiles REST_staticFiles}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_staticFileResponseHeaders REST_staticFileResponseHeaders}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_classpathResourceFinder REST_classpathResourceFinder}
+ <li>{@link org.apache.juneau.rest.RestContext#REST_useClasspathResourceCaching REST_useClasspathResourceCaching}
+ </ul>
+ <li>
+ Support for static files has been simplified and improved.
+ <ul>
+ <li>Syntax on {@link org.apache.juneau.rest.annotation.RestResource#staticFiles()} has been simplified, and
+ now allows you to specify response headers in the strings.
+ <li>Response headers for static files can also be configured through
+ {@link org.apache.juneau.rest.RestContext#REST_staticFileResponseHeaders REST_staticFileResponseHeaders}.
+ <li>Static file in-memory caching now configurable through
+ {@link org.apache.juneau.rest.RestContext#REST_useClasspathResourceCaching REST_useClasspathResourceCaching}.
+ <li>Static file retrieval can be customized through
+ {@link org.apache.juneau.rest.RestContext#REST_classpathResourceFinder REST_classpathResourceFinder}
+ </ul>
<li>
Eliminated the <code>RestMatcherReflecting</code> class.
<br>You can now simply create a {@link org.apache.juneau.rest.RestMatcher} that has a public constructor that
@@ -7968,6 +8017,58 @@
<li>
<code>@RestMethod.serializersInherit</code> and <code>@RestMethod.parsersInherit</code> replaced with
simplified {@link org.apache.juneau.rest.annotation.RestMethod#inherit()}.
+ <li>
+ Changes to {@link org.apache.juneau.rest.RequestFormData}:
+ <ul>
+ <li>{@link org.apache.juneau.rest.RequestFormData#addDefault(Map) addDefault(Map)} takes in a
+ <code>Map<String,Object></code> instead of <code>Map<String,String></code>.
+ </ul>
+ <li>
+ Changes to {@link org.apache.juneau.rest.RequestHeaders}:
+ <ul>
+ <li>{@link org.apache.juneau.rest.RequestHeaders#addDefault(Map) addDefault(Map)} takes in a
+ <code>Map<String,Object></code> instead of <code>Map<String,String></code>.
+ </ul>
+ <li>
+ Changes to {@link org.apache.juneau.rest.RequestQuery}:
+ <ul>
+ <li>{@link org.apache.juneau.rest.RequestQuery#addDefault(Map) addDefault(Map)} takes in a
+ <code>Map<String,Object></code> instead of <code>Map<String,String></code>.
+ </ul>
+ <li>
+ Changes to {@link org.apache.juneau.rest.RestContext}:
+ <ul>
+ <li><code>getResource(String,Locale)</code> renamed to {@link org.apache.juneau.rest.RestContext#getClasspathResource(String,Locale) getClasspathResource(String,Locale)}
+ <li><code>getResourceAsString(String,Locale)</code> renamed to {@link org.apache.juneau.rest.RestContext#getClasspathResourceAsString(String,Locale) getClasspathResourceAsString(String,Locale)}
+ <li><code>getResource(Class,MediaType,String,Locale)</code> renamed to {@link org.apache.juneau.rest.RestContext#getClasspathResource(Class,MediaType,String,Locale) getClasspathResourceAsString(Class,MediaType,String,Locale)}
+ <li>New method {@link org.apache.juneau.rest.RestContext#getClasspathResource(Class,String,Locale) getClasspathResource(Class,String,Locale)}.
+ <li>New method {@link org.apache.juneau.rest.RestContext#getClasspathResourceAsString(Class,String,Locale) getClasspathResourceAsString(Class,String,Locale)}.
+ <li>New method {@link org.apache.juneau.rest.RestContext#getClasspathResource(Class,Class,MediaType,String,Locale) getClasspathResource(Class,Class,MediaType,String,Locale)}.
+ <li>{@link org.apache.juneau.rest.RestContext#getDefaultRequestHeaders() getDefaultRequestHeaders} returns a
+ <code>Map<String,Object></code> instead of <code>Map<String,String></code>.
+ <li>{@link org.apache.juneau.rest.RestContext#getDefaultResponseHeaders() getDefaultRequestHeaders} returns a
+ <code>Map<String,Object></code> instead of <code>Map<String,String></code>.
+ </ul>
+ <li>
+ Changes to {@link org.apache.juneau.rest.RestRequest}:
+ <ul>
+ <li><code>getSupportedMediaTypes()</code> replaced with
+ {@link org.apache.juneau.rest.RestRequest#getSupportedAcceptTypes() getSupportedAcceptTypes()} and
+ {@link org.apache.juneau.rest.RestRequest#getSupportedContentTypes() getSupportedContentTypes()}.
+ <li><code>getReaderResource(String,boolean,MediaType)</code> renamed to
+ {@link org.apache.juneau.rest.RestRequest#getClasspathReaderResource(String,boolean,MediaType) getClasspathReaderResource(String,boolean,MediaType)}
+ <li><code>getReaderResource(String,boolean)</code> renamed to
+ {@link org.apache.juneau.rest.RestRequest#getClasspathReaderResource(String,boolean) getClasspathReaderResource(String,boolean)}
+ <li><code>getReaderResource(String)</code> renamed to
+ {@link org.apache.juneau.rest.RestRequest#getClasspathReaderResource(String) getClasspathReaderResource(String)}
+ </ul>
+ <li>
+ Changes to {@link org.apache.juneau.rest.annotation.RestMethod}:
+ <ul>
+ <li>New {@link org.apache.juneau.rest.annotation.RestMethod#supportedAcceptTypes() supportedAcceptTypes()} and
+ {@link org.apache.juneau.rest.annotation.RestMethod#supportedContentTypes() supportedContentTypes()}
+ for overriding the supported media types inferred from the serializers and parsers.
+ </ul>
</ul>
<h6 class='topic'>juneau-rest-client</h6>
@@ -7980,6 +8081,12 @@
<br>The default value is now {@link org.apache.juneau.httppart.SimpleUonPartSerializer} which will
serialize strings as plain-text and collections/arrays as comma-delimited lists.
<br>We decided to change the default behavior in favor of practicality over purity.
+ <li>
+ New methods on {@link org.apache.juneau.rest.client.RestCall} class:
+ <ul>
+ <li>{@link org.apache.juneau.rest.client.RestCall#getResponseHeader(String) getResponseHeader(String)}
+ <li>{@link org.apache.juneau.rest.client.RestCall#getResponseCode() getResponseCode()}
+ </ul>
</ul>
</div>
@@ -8680,7 +8787,7 @@
<li><code><del>HTMLDOC_stylesheet</del></code> - Was <jsf>HTMLDOC_cssUrl</jsf>. Now an array.
</ul>
<li>
- New {@link org.apache.juneau.utils.ResourceFinder} utility class.
+ New <code><del>ResourceFinder</del></code> utility class.
Allows you to search for resources up the parent hierarchy chain.
Also allows you to search for localized resources.
<li>
@@ -10383,8 +10490,8 @@
<li>Fixed a bug in the stack trace hash algorithm in {@link org.apache.juneau.rest.RestException}.
<li>New methods in {@link org.apache.juneau.rest.RestRequest}:
<ul>
- <li>{@link org.apache.juneau.rest.RestRequest#getReaderResource(String)} - Replaces <code>getVarResource(String)</code>.
- <li>{@link org.apache.juneau.rest.RestRequest#getReaderResource(String,boolean)}
+ <li><code><del>RestRequest.getReaderResource(String)</del></code> - Replaces <code>getVarResource(String)</code>.
+ <li><code><del>RestRequest.getReaderResource(String,boolean)</del></code>
<li><code><del>RestRequest.getReaderResource(String,boolean,String)</del></code>
</ul>
<li>Changes in {@link org.apache.juneau.rest.RestResponse}:
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java
----------------------------------------------------------------------
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java
index d34be25..7c355e7 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java
@@ -65,7 +65,8 @@ import org.apache.juneau.transforms.*;
head={
"<link rel='icon' href='$U{servlet:/htdocs/cat.png}'/>"
}
- )
+ ),
+ staticFiles={"htdocs:htdocs"}
)
public class PetStoreResource extends ResourceJena {
private static final long serialVersionUID = 1L;
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/InheritanceResource.java
----------------------------------------------------------------------
diff --git a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/InheritanceResource.java b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/InheritanceResource.java
index 492b9a5..a722d1e 100644
--- a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/InheritanceResource.java
+++ b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/InheritanceResource.java
@@ -103,7 +103,7 @@ public class InheritanceResource extends RestServlet {
path="/test1"
)
public Reader test1(RestRequest req) {
- return new StringReader(new ObjectList(req.getSupportedMediaTypes()).toString());
+ return new StringReader(new ObjectList(req.getSupportedContentTypes()).toString());
}
// Should show ['text/p5']
@@ -113,7 +113,7 @@ public class InheritanceResource extends RestServlet {
parsers=P5.class
)
public Reader test2(RestRequest req) {
- return new StringReader(new ObjectList(req.getSupportedMediaTypes()).toString());
+ return new StringReader(new ObjectList(req.getSupportedContentTypes()).toString());
}
// Should show ['text/p5','text/p3','text/p4','text/p1','text/p2']
@@ -124,7 +124,7 @@ public class InheritanceResource extends RestServlet {
inherit="PARSERS"
)
public Reader test3(RestRequest req) {
- return new StringReader(new ObjectList(req.getSupportedMediaTypes()).toString());
+ return new StringReader(new ObjectList(req.getSupportedContentTypes()).toString());
}
}
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/StaticFilesResource.java
----------------------------------------------------------------------
diff --git a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/StaticFilesResource.java b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/StaticFilesResource.java
index c6c2c10..1b0856b 100644
--- a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/StaticFilesResource.java
+++ b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/StaticFilesResource.java
@@ -22,7 +22,7 @@ import org.apache.juneau.rest.annotation.*;
*/
@RestResource(
path="/testStaticFiles",
- staticFiles="{xdocs:'xdocs'}"
+ staticFiles={"xdocs:xdocs","xdocs2:xdocs2:{Foo:'Bar'}"}
)
public class StaticFilesResource extends RestServlet {
private static final long serialVersionUID = 1L;
@@ -34,5 +34,4 @@ public class StaticFilesResource extends RestServlet {
public String testXdocs() {
return null;
}
-
}
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/xdocs/xdocs/test.txt
----------------------------------------------------------------------
diff --git a/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/xdocs/xdocs/test.txt b/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/xdocs/xdocs/test.txt
deleted file mode 100644
index e3db156..0000000
--- a/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/xdocs/xdocs/test.txt
+++ /dev/null
@@ -1,13 +0,0 @@
- ***************************************************************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations under the License. *
- ***************************************************************************************************************************
- OK-2
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/xdocs/xsubdocs/test.txt
----------------------------------------------------------------------
diff --git a/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/xdocs/xsubdocs/test.txt b/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/xdocs/xsubdocs/test.txt
new file mode 100644
index 0000000..e3db156
--- /dev/null
+++ b/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/xdocs/xsubdocs/test.txt
@@ -0,0 +1,13 @@
+ ***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations under the License. *
+ ***************************************************************************************************************************
+ OK-2
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/xdocs2/test.txt
----------------------------------------------------------------------
diff --git a/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/xdocs2/test.txt b/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/xdocs2/test.txt
new file mode 100644
index 0000000..b734fee
--- /dev/null
+++ b/juneau-microservice/juneau-microservice-test/src/main/resources/org/apache/juneau/rest/test/xdocs2/test.txt
@@ -0,0 +1,13 @@
+ ***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations under the License. *
+ ***************************************************************************************************************************
+ OK-3
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/StaticFilesTest.java
----------------------------------------------------------------------
diff --git a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/StaticFilesTest.java b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/StaticFilesTest.java
index 42c4c9b..4e2167c 100644
--- a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/StaticFilesTest.java
+++ b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/StaticFilesTest.java
@@ -32,22 +32,62 @@ public class StaticFilesTest extends RestTestcase {
r = client.doGet(url + "/test.txt").getResponseAsString();
assertTrue(r.endsWith("OK-1"));
- r = client.doGet(url + "/xdocs/test.txt").getResponseAsString();
+ r = client.doGet(url + "/xsubdocs/test.txt").getResponseAsString();
assertTrue(r.endsWith("OK-2"));
// For security reasons, paths containing ".." should always return 404.
try {
- client.doGet(url + "/xdocs/../test.txt?noTrace=true").connect();
+ client.doGet(url + "/xsubdocs/../test.txt?noTrace=true").connect();
fail("404 exception expected");
} catch (RestCallException e) {
assertEquals(404, e.getResponseCode());
}
try {
- client.doGet(url + "/xdocs/%2E%2E/test.txt?noTrace=true").connect();
+ client.doGet(url + "/xsubdocs/%2E%2E/test.txt?noTrace=true").connect();
fail("404 exception expected");
} catch (RestCallException e) {
assertEquals(404, e.getResponseCode());
}
}
+
+ //====================================================================================================
+ // Tests the @RestResource(staticFiles) annotation.
+ //====================================================================================================
+ @Test
+ public void testXdocsPreventPathTraversal() throws Exception {
+ RestClient client = TestMicroservice.DEFAULT_CLIENT_PLAINTEXT;
+ String url = URL + "/xdocs";
+
+ // For security reasons, paths containing ".." should always return 404.
+ try {
+ client.doGet(url + "/xsubdocs/../test.txt?noTrace=true").connect();
+ fail("404 exception expected");
+ } catch (RestCallException e) {
+ assertEquals(404, e.getResponseCode());
+ }
+
+ try {
+ client.doGet(url + "/xsubdocs/%2E%2E/test.txt?noTrace=true").connect();
+ fail("404 exception expected");
+ } catch (RestCallException e) {
+ assertEquals(404, e.getResponseCode());
+ }
+ }
+
+ //====================================================================================================
+ // Tests the @RestResource(staticFiles) annotation.
+ //====================================================================================================
+ @Test
+ public void testXdocsWithHeader() throws Exception {
+ RestClient client = TestMicroservice.DEFAULT_CLIENT_PLAINTEXT;
+ String r;
+ String url = URL + "/xdocs2";
+
+ r = client.doGet(url + "/test.txt").getResponseAsString();
+ assertTrue(r.endsWith("OK-3"));
+
+ r = client.doGet(url + "/test.txt").getResponseHeader("Foo");
+ assertEquals("Bar", r);
+ }
}
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
index a24fee5..ba064a2 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
@@ -1733,7 +1733,11 @@ public final class RestCall extends BeanSession {
/**
* Connects to the remote resource (if {@code connect()} hasn't already been called) and returns the HTTP response
* message body as plain text.
- *
+ *
+ * <p>
+ * The response entity is discarded unless one of the pipe methods have been specified to pipe the output to an
+ * output stream or writer.
+ *
* @return The response as a string.
* @throws RestCallException If an exception or non-200 response code occurred during the connection attempt.
* @throws IOException If an exception occurred while streaming was already occurring.
@@ -1748,6 +1752,53 @@ public final class RestCall extends BeanSession {
close();
}
}
+
+ /**
+ * Connects to the remote resource (if {@code connect()} hasn't already been called) and returns the value of
+ * an HTTP header on the response.
+ *
+ * <p>
+ * Useful if you're only interested in a particular header value from the response and not the body of the response.
+ *
+ * <p>
+ * The response entity is discarded unless one of the pipe methods have been specified to pipe the output to an
+ * output stream or writer.
+ *
+ * @param name The header name.
+ * @return The response header as a string, or <jk>null</jk> if the header was not found.
+ * @throws RestCallException If an exception or non-200 response code occurred during the connection attempt.
+ * @throws IOException If an exception occurred while streaming was already occurring.
+ */
+ public String getResponseHeader(String name) throws IOException {
+ try {
+ HttpResponse r = getResponse();
+ Header h = r.getFirstHeader(name);
+ return h == null ? null : h.getValue();
+ } catch (IOException e) {
+ isFailed = true;
+ throw e;
+ } finally {
+ close();
+ }
+ }
+
+ /**
+ * Connects to the remote resource (if {@code connect()} hasn't already been called) and returns the HTTP response code.
+ *
+ * <p>
+ * Useful if you're only interested in the status code and not the body of the response.
+ *
+ * <p>
+ * The response entity is discarded unless one of the pipe methods have been specified to pipe the output to an
+ * output stream or writer.
+ *
+ * @return The response code.
+ * @throws RestCallException If an exception or non-200 response code occurred during the connection attempt.
+ * @throws IOException If an exception occurred while streaming was already occurring.
+ */
+ public int getResponseCode() throws IOException {
+ return run();
+ }
/**
* Same as {@link #getResponse(Class)} but allows you to run the call asynchronously.
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java
index ebdbc68..0330c20 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java
@@ -28,6 +28,7 @@ import javax.servlet.http.*;
import org.apache.juneau.*;
import org.apache.juneau.dto.swagger.*;
import org.apache.juneau.encoders.*;
+import org.apache.juneau.http.*;
import org.apache.juneau.httppart.*;
import org.apache.juneau.httppart.HttpPartParser;
import org.apache.juneau.internal.*;
@@ -57,7 +58,7 @@ class CallMethod implements Comparable<CallMethod> {
private final HttpPartParser partParser;
private final HttpPartSerializer partSerializer;
private final ObjectMap properties;
- private final Map<String,String> defaultRequestHeaders, defaultQuery, defaultFormData;
+ private final Map<String,Object> defaultRequestHeaders, defaultQuery, defaultFormData;
private final String defaultCharset;
private final long maxInput;
private final boolean deprecated;
@@ -68,6 +69,7 @@ class CallMethod implements Comparable<CallMethod> {
private final RestContext context;
private final BeanContext beanContext;
private final Map<String,Widget> widgets;
+ private final List<MediaType> supportedAcceptTypes, supportedContentTypes;
CallMethod(Object servlet, java.lang.reflect.Method method, RestContext context) throws RestServletException {
Builder b = new Builder(servlet, method, context);
@@ -100,6 +102,8 @@ class CallMethod implements Comparable<CallMethod> {
this.priority = b.priority;
this.parameters = b.parameters;
this.responses = b.responses;
+ this.supportedAcceptTypes = b.supportedAcceptTypes;
+ this.supportedContentTypes = b.supportedContentTypes;
this.widgets = Collections.unmodifiableMap(b.widgets);
}
@@ -117,13 +121,14 @@ class CallMethod implements Comparable<CallMethod> {
HttpPartSerializer partSerializer;
BeanContext beanContext;
ObjectMap properties;
- Map<String,String> defaultRequestHeaders, defaultQuery, defaultFormData;
+ Map<String,Object> defaultRequestHeaders, defaultQuery, defaultFormData;
boolean deprecated;
long maxInput;
Integer priority;
org.apache.juneau.rest.annotation.Parameter[] parameters;
Response[] responses;
Map<String,Widget> widgets;
+ List<MediaType> supportedAcceptTypes, supportedContentTypes;
Builder(Object servlet, java.lang.reflect.Method method, RestContext context) throws RestServletException {
String sig = method.getDeclaringClass().getName() + '.' + method.getName();
@@ -397,6 +402,15 @@ class CallMethod implements Comparable<CallMethod> {
if (bcb != null)
beanContext = bcb.build();
+ supportedAcceptTypes =
+ m.supportedAcceptTypes().length > 0
+ ? Collections.unmodifiableList(new ArrayList<>(Arrays.asList(MediaType.forStrings(m.supportedAcceptTypes()))))
+ : serializers.getSupportedMediaTypes();
+ supportedContentTypes =
+ m.supportedContentTypes().length > 0
+ ? Collections.unmodifiableList(new ArrayList<>(Arrays.asList(MediaType.forStrings(m.supportedContentTypes()))))
+ : parsers.getSupportedMediaTypes();
+
params = context.findParams(method, pathPattern, false);
// Need this to access methods in anonymous inner classes.
@@ -780,7 +794,7 @@ class CallMethod implements Comparable<CallMethod> {
ObjectMap requestProperties = new ResolvingObjectMap(req.getVarResolverSession()).setInner(properties);
req.init(method, requestProperties, defaultRequestHeaders, defaultQuery, defaultFormData, defaultCharset,
- maxInput, serializers, parsers, partParser, beanContext, encoders, widgets);
+ maxInput, serializers, parsers, partParser, beanContext, encoders, widgets, supportedAcceptTypes, supportedContentTypes);
res.init(requestProperties, defaultCharset, serializers, partSerializer, encoders);
// Class-level guards
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormData.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormData.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormData.java
index 051eee5..4549870 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormData.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormData.java
@@ -52,13 +52,14 @@ public class RequestFormData extends LinkedHashMap<String,String[]> {
* @param defaultEntries The default entries. Can be <jk>null</jk>.
* @return This object (for method chaining).
*/
- public RequestFormData addDefault(Map<String,String> defaultEntries) {
+ public RequestFormData addDefault(Map<String,Object> defaultEntries) {
if (defaultEntries != null) {
- for (Map.Entry<String,String> e : defaultEntries.entrySet()) {
- String key = e.getKey(), value = e.getValue();
+ for (Map.Entry<String,Object> e : defaultEntries.entrySet()) {
+ String key = e.getKey();
+ Object value = e.getValue();
String[] v = get(key);
if (v == null || v.length == 0 || StringUtils.isEmpty(v[0]))
- put(key, new String[]{value});
+ put(key, new String[]{StringUtils.toString(value)});
}
}
return this;
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeaders.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeaders.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeaders.java
index fe6b675..a08bbd7 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeaders.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeaders.java
@@ -67,13 +67,14 @@ public class RequestHeaders extends TreeMap<String,String[]> {
* @param defaultEntries The default entries. Can be <jk>null</jk>.
* @return This object (for method chaining).
*/
- public RequestHeaders addDefault(Map<String,String> defaultEntries) {
+ public RequestHeaders addDefault(Map<String,Object> defaultEntries) {
if (defaultEntries != null) {
- for (Map.Entry<String,String> e : defaultEntries.entrySet()) {
- String key = e.getKey(), value = e.getValue();
+ for (Map.Entry<String,Object> e : defaultEntries.entrySet()) {
+ String key = e.getKey();
+ Object value = e.getValue();
String[] v = get(key);
if (v == null || v.length == 0 || StringUtils.isEmpty(v[0]))
- put(key, new String[]{value});
+ put(key, new String[]{StringUtils.toString(value)});
}
}
return this;
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQuery.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQuery.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQuery.java
index 2e51c39..8f1d62f 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQuery.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQuery.java
@@ -65,13 +65,14 @@ public final class RequestQuery extends LinkedHashMap<String,String[]> {
* @param defaultEntries The default entries. Can be <jk>null</jk>.
* @return This object (for method chaining).
*/
- public RequestQuery addDefault(Map<String,String> defaultEntries) {
+ public RequestQuery addDefault(Map<String,Object> defaultEntries) {
if (defaultEntries != null) {
- for (Map.Entry<String,String> e : defaultEntries.entrySet()) {
- String key = e.getKey(), value = e.getValue();
+ for (Map.Entry<String,Object> e : defaultEntries.entrySet()) {
+ String key = e.getKey();
+ Object value = e.getValue();
String[] v = get(key);
if (v == null || v.length == 0 || StringUtils.isEmpty(v[0]))
- put(key, new String[]{value});
+ put(key, new String[]{StringUtils.toString(value)});
}
}
return this;