http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Queryable.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Queryable.java b/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Queryable.java new file mode 100644 index 0000000..297097f --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Queryable.java @@ -0,0 +1,96 @@ +// *************************************************************************************************************************** +// * 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.rest.converters; + +import static javax.servlet.http.HttpServletResponse.*; + +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.parser.*; +import org.apache.juneau.rest.*; +import org.apache.juneau.serializer.*; +import org.apache.juneau.utils.*; + +/** + * Converter for enablement of {@link PojoQuery} support on response objects returned by a <code>@RestMethod</code> method. + * <p> + * When enabled, objects in a POJO tree can be filtered using the functionality described in the {@link PojoQuery} + * class. + * <p> + * The following HTTP request parameters are available for tabular data (e.g. {@code Collections} of {@code Maps}, arrays of beans, etc...): + * <ul class='spaced-list'> + * <li><b>&q=<i>JSON-object</i></b> - Query parameter. Only return rows that match the specified search string. <br> + * The JSON object keys are column names, and the values are search parameter strings.<br> + * Example: <code>&s=(name=Bill*,birthDate=>2000)</code> + * <li><b>&v=<i>JSON-array or comma-delimited list</i></b> - View parameter. Only return the specified columns.<br> + * Example: <code>&v=(name,birthDate)</code> + * <li><b>&s=<i>JSON-object</i></b> - Sort parameter. Sort the results by the specified columns.<br> + * The JSON object keys are the column names, and the values are either {@code 'A'} for ascending or {@code 'D'} for descending. + * Example: <code>&s=(name=A,birthDate=D)</code> + * <li><b>&i=<i>true/false</i></b> - Case-insensitive parameter. Specify <jk>true</jk> for case-insensitive matching on the {@code &q} parameter. + * <li><b>&p=<i>number</i></b> - Position parameter. Only return rows starting at the specified index position (zero-indexed). Default is {@code 0}. + * <li><b>&q=<i>number</i></b> - Limit parameter. Only return the specified number of rows. Default is {@code 0} (meaning return all rows). + * </ul> + * + * <p> + * The <b>&v</b> parameter can also be used on {@code Maps} and beans. + * + * <p> + * See {@link PojoQuery} for additional information on filtering POJO models. + */ +public final class Queryable implements RestConverter { + + @Override /* RestConverter */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Object convert(RestRequest req, Object o, ClassMeta cm) { + if (o == null) + return null; + + try { + + // If no actual filtering parameters have been passed in, and there is no map augmenter specified, + // then just pass the original object back. + if (req.hasAnyQueryParameters("q","v","s","g","i","p","l")) { + BeanSession session = req.getBeanSession(); + + if (cm.getPojoSwap() != null) + o = cm.getPojoSwap().swap(session, o); + + PojoQuery f = new PojoQuery(o, session); + + if (o instanceof Collection || o.getClass().isArray()) { + ObjectMap query = req.getQueryParameter("q", ObjectMap.class); + ClassMeta<List<String>> cm1 = session.getCollectionClassMeta(List.class, String.class); + List<String> view = req.getQueryParameter("v", cm1); + ClassMeta<List<Object>> cm2 = session.getCollectionClassMeta(List.class, String.class); + List sort = req.getQueryParameter("s", cm2); + boolean ignoreCase = req.getQueryParameter("i", Boolean.class, false); + int pos = req.getQueryParameter("p", Integer.class, 0); + int limit = req.getQueryParameter("l", Integer.class, 0); + o = f.filterCollection(query, view, sort, pos, limit, ignoreCase); + + } else { + ClassMeta<List<String>> cm2 = session.getCollectionClassMeta(List.class, String.class); + List<String> view = req.getQueryParameter("v", cm2); + o = f.filterMap(view); + } + } + return o; + } catch (SerializeException e) { + throw new RestException(SC_BAD_REQUEST, e); + } catch (ParseException e) { + throw new RestException(SC_BAD_REQUEST, e); + } + } +}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Traversable.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Traversable.java b/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Traversable.java new file mode 100644 index 0000000..9dfe411 --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/converters/Traversable.java @@ -0,0 +1,67 @@ +// *************************************************************************************************************************** +// * 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.rest.converters; + +import javax.servlet.http.*; + +import org.apache.juneau.*; +import org.apache.juneau.rest.*; +import org.apache.juneau.serializer.*; +import org.apache.juneau.utils.*; + +/** + * Converter for enablement of {@link PojoRest} support on response objects returned by a <code>@RestMethod</code> method. + * <p> + * When enabled, objects in a POJO tree returned by the REST method can be addressed through additional URL path information. + * + * <p class='bcode'> + * <jc>// Resource method on resource "http://localhost:8080/sample/addressBook"</jc> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>, converters=Traversable.<jk>class</jk>) + * <jk>public void</jk> doGet(RestRequest req, RestResponse res) { + * <jk>return new</jk> AddressBook(); + * } + * + * <jc>// Sample usage</jc> + * <jk>public static void</jk> main(String[] args) { + * <jc>// Get the zip code of the 2nd address of the first person in the address book.</jc> + * RestCall r = <jk>new</jk> RestClient().doGet(<js>"http://localhost:8080/sample/addressBook/0/addresses/1/zip"</js>); + * <jk>int</jk> zip = r.getResponse(Integer.<jk>class</jk>); + * } + * </p> + * <p> + * See {@link PojoRest} for additional information on addressing elements in a POJO tree using URL notation. + */ +public final class Traversable implements RestConverter { + + @Override /* RestConverter */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public Object convert(RestRequest req, Object o, ClassMeta cm) throws RestException { + if (o == null) + return null; + + if (req.getPathRemainder() != null) { + try { + if (cm.getPojoSwap() != null) + o = cm.getPojoSwap().swap(req.getBeanSession(), o); + PojoRest p = new PojoRest(o, req.getReaderParser()); + o = p.get(req.getPathRemainder()); + } catch (SerializeException e) { + throw new RestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e); + } catch (PojoRestException e) { + throw new RestException(e.getStatus(), e); + } + } + + return o; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/converters/package.html ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/converters/package.html b/juneau-rest/src/main/java/org/apache/juneau/rest/converters/package.html new file mode 100644 index 0000000..2599329 --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/converters/package.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<!-- +/*************************************************************************************************************************** + * 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. + * + ***************************************************************************************************************************/ + --> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <style type="text/css"> + /* For viewing in Page Designer */ + @IMPORT url("../../../../javadoc.css"); + + /* For viewing in REST interface */ + @IMPORT url("../htdocs/javadoc.css"); + body { + margin: 20px; + } + </style> + <script> + /* Replace all @code and @link tags. */ + window.onload = function() { + document.body.innerHTML = document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>'); + document.body.innerHTML = document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, '<code>$3</code>'); + } + </script> +</head> +<body> +<p>Predefined REST response converters</p> +</body> +</html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBook.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBook.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBook.png new file mode 100644 index 0000000..96426b7 Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBook.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBookJson.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBookJson.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBookJson.png new file mode 100644 index 0000000..68c0ec8 Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBookJson.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBookOptions.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBookOptions.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBookOptions.png new file mode 100644 index 0000000..36c3e42 Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBookOptions.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBook_juneaustyle.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBook_juneaustyle.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBook_juneaustyle.png new file mode 100644 index 0000000..94327eb Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/AddressBook_juneaustyle.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource1.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource1.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource1.png new file mode 100644 index 0000000..3b54341 Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource1.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource2.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource2.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource2.png new file mode 100644 index 0000000..7a4c816 Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource2.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource3.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource3.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource3.png new file mode 100644 index 0000000..dd088bd Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource3.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource4.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource4.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource4.png new file mode 100644 index 0000000..17bdbf6 Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResource4.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResourceOptions.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResourceOptions.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResourceOptions.png new file mode 100644 index 0000000..8e64467 Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResourceOptions.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResourceOptionsJson.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResourceOptionsJson.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResourceOptionsJson.png new file mode 100644 index 0000000..b87a317 Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/HelloWorldResourceOptionsJson.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/Options2.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/Options2.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/Options2.png new file mode 100644 index 0000000..52b9ad1 Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/Options2.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/OptionsPage.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/OptionsPage.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/OptionsPage.png new file mode 100644 index 0000000..c524ede Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/OptionsPage.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/Samples_RootResources.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/Samples_RootResources.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/Samples_RootResources.png new file mode 100644 index 0000000..62408e2 Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/Samples_RootResources.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/UrlEncodedForm.png ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/UrlEncodedForm.png b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/UrlEncodedForm.png new file mode 100644 index 0000000..2cd173f Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/doc-files/UrlEncodedForm.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java b/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java new file mode 100644 index 0000000..2381736 --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java @@ -0,0 +1,189 @@ +// *************************************************************************************************************************** +// * 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.rest.jaxrs; + +import static javax.servlet.http.HttpServletResponse.*; + +import java.io.*; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.*; + +import javax.ws.rs.*; +import javax.ws.rs.core.*; +import javax.ws.rs.ext.*; + +import org.apache.juneau.*; +import org.apache.juneau.internal.*; +import org.apache.juneau.parser.*; +import org.apache.juneau.rest.annotation.*; +import org.apache.juneau.serializer.*; + +/** + * Base class for defining JAX-RS providers based on Juneau serializers and parsers. + */ +public class BaseProvider implements MessageBodyReader<Object>, MessageBodyWriter<Object> { + + private SerializerGroup serializers = new SerializerGroup(); + private ParserGroup parsers = new ParserGroup(); + private ObjectMap properties = new ObjectMap(); + + /** + * Constructor. + */ + protected BaseProvider() { + try { + properties = new ObjectMap(); + JuneauProvider jp = getClass().getAnnotation(JuneauProvider.class); + serializers.append(jp.serializers()); + parsers.append(jp.parsers()); + for (Property p : jp.properties()) + properties.put(p.name(), p.value()); + serializers.addBeanFilters(jp.beanFilters()); + parsers.addBeanFilters(jp.beanFilters()); + serializers.addPojoSwaps(jp.pojoSwaps()); + parsers.addPojoSwaps(jp.pojoSwaps()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Returns properties defined on the specified method through the {@link RestMethod#properties()} + * annotation specified on the method and the {@link JuneauProvider#properties()} annotation + * specified on the provider class. + * + * @param a All annotations defined on the method. + * @return A map of all properties define on the method. + */ + protected ObjectMap getMethodProperties(Annotation[] a) { + ObjectMap m = new ObjectMap().setInner(properties); + for (Annotation aa : a) { + if (aa instanceof RestMethod) { + for (Property p : ((RestMethod)aa).properties()) + m.put(p.name(), p.value()); + } + } + return m; + } + + @Override /* MessageBodyWriter */ + public long getSize(Object o, Class<?> type, Type gType, Annotation[] a, MediaType mediaType) { + return -1; + } + + @Override /* MessageBodyWriter */ + public boolean isWriteable(Class<?> type, Type gType, Annotation[] a, MediaType mediaType) { + return serializers.findMatch(mediaType.toString()) != null; + } + + @Override /* MessageBodyWriter */ + public void writeTo(Object o, Class<?> type, Type gType, Annotation[] a, MediaType mediaType, + MultivaluedMap<String,Object> headers, OutputStream out) throws IOException, WebApplicationException { + try { + String mt = serializers.findMatch(mediaType.toString()); + if (mt == null) + throw new WebApplicationException(SC_NOT_ACCEPTABLE); + Serializer s = serializers.getSerializer(mt); + ObjectMap mp = getMethodProperties(a); + mp.append("mediaType", mediaType.toString()); + Locale locale = getLocale(headers); + TimeZone timeZone = getTimeZone(headers); + if (s.isWriterSerializer()) { + WriterSerializer s2 = (WriterSerializer)s; + OutputStreamWriter w = new OutputStreamWriter(out, IOUtils.UTF8); + SerializerSession session = s.createSession(w, mp, null, locale, timeZone); + s2.serialize(session, o); + w.flush(); + w.close(); + } else { + OutputStreamSerializer s2 = (OutputStreamSerializer)s; + SerializerSession session = s.createSession(s2, mp, null, locale, timeZone); + s2.serialize(session, o); + out.flush(); + out.close(); + } + } catch (SerializeException e) { + throw new IOException(e); + } + } + + @Override /* MessageBodyReader */ + public boolean isReadable(Class<?> type, Type gType, Annotation[] a, MediaType mediaType) { + return parsers.findMatch(mediaType.toString()) != null; + } + + @Override /* MessageBodyReader */ + public Object readFrom(Class<Object> type, Type gType, Annotation[] a, MediaType mediaType, + MultivaluedMap<String,String> headers, InputStream in) throws IOException, WebApplicationException { + try { + String mt = parsers.findMatch(mediaType.toString()); + if (mt == null) + throw new WebApplicationException(SC_UNSUPPORTED_MEDIA_TYPE); + Parser p = parsers.getParser(mt); + BeanContext bc = p.getBeanContext(); + ClassMeta<?> cm = bc.getClassMeta(gType); + ObjectMap mp = getMethodProperties(a); + mp.put("mediaType", mediaType.toString()); + Locale locale = getLocale(headers); + TimeZone timeZone = getTimeZone(headers); + if (p.isReaderParser()) { + ReaderParser p2 = (ReaderParser)p; + InputStreamReader r = new InputStreamReader(in, IOUtils.UTF8); + ParserSession session = p2.createSession(r, mp, null, null, locale, timeZone); + return p2.parse(session, cm); + } + InputStreamParser p2 = (InputStreamParser)p; + ParserSession session = p2.createSession(in, mp, null, null, locale, timeZone); + return p2.parse(session, cm); + } catch (ParseException e) { + throw new IOException(e); + } + } + + @SuppressWarnings("rawtypes") + private static Locale getLocale(MultivaluedMap headers) { + if (headers.containsKey("Accept-Language") && headers.get("Accept-Language") != null) { + String h = String.valueOf(headers.get("Accept-Language")); + if (h != null) { + MediaRange[] mr = MediaRange.parse(h); + if (mr.length > 0) + return toLocale(mr[0].getType()); + } + } + return null; + } + + /* + * Converts an Accept-Language value entry to a Locale. + */ + private static Locale toLocale(String lang) { + String country = ""; + int i = lang.indexOf('-'); + if (i > -1) { + country = lang.substring(i+1).trim(); + lang = lang.substring(0,i).trim(); + } + return new Locale(lang, country); + } + + @SuppressWarnings("rawtypes") + private static TimeZone getTimeZone(MultivaluedMap headers) { + if (headers.containsKey("Time-Zone") && headers.get("Time-Zone") != null) { + String h = String.valueOf(headers.get("Time-Zone")); + return TimeZone.getTimeZone(h); + } + return null; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/DefaultProvider.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/DefaultProvider.java b/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/DefaultProvider.java new file mode 100644 index 0000000..92cc4a1 --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/DefaultProvider.java @@ -0,0 +1,71 @@ +// *************************************************************************************************************************** +// * 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.rest.jaxrs; + +import javax.ws.rs.*; +import javax.ws.rs.ext.*; + +import org.apache.juneau.html.*; +import org.apache.juneau.jso.*; +import org.apache.juneau.json.*; +import org.apache.juneau.rest.*; +import org.apache.juneau.soap.*; +import org.apache.juneau.urlencoding.*; +import org.apache.juneau.xml.*; + +/** + * JAX-RS provider for the same serialize/parse support provided by the {@link RestServletDefault} class. + */ +@Provider +@Produces({ + "application/json", "text/json", // JsonSerializer + "application/json+simple", "text/json+simple", // JsonSerializer.Simple + "application/json+schema", // JsonSchemaSerializer + "text/xml", // XmlDocSerializer + "text/xml+simple", // XmlDocSerializer.Simple + "text/xml+schema", // XmlSchemaDocSerializer + "text/html", // HtmlDocSerializer + "application/x-www-form-urlencoded", // UrlEncodingSerializer + "text/xml+soap", // SoapXmlSerializer + "application/x-java-serialized-object" // JavaSerializedObjectSerializer +}) +@Consumes({ + "application/json", "text/json", // JsonParser + "text/xml", // XmlParser + "text/html", // HtmlParser + "application/x-www-form-urlencoded", // UrlEncodingParser + "application/x-java-serialized-object" // JavaSerializedObjectParser +}) +@JuneauProvider( + serializers={ + JsonSerializer.class, + JsonSerializer.Simple.class, + JsonSchemaSerializer.class, + XmlDocSerializer.class, + XmlDocSerializer.Simple.class, + XmlSchemaDocSerializer.class, + HtmlDocSerializer.class, + UrlEncodingSerializer.class, + SoapXmlSerializer.class, + JavaSerializedObjectSerializer.class + }, + parsers={ + JsonParser.class, + XmlParser.class, + HtmlParser.class, + UrlEncodingParser.class, + JavaSerializedObjectParser.class + } +) +public final class DefaultProvider extends BaseProvider {} + http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/JuneauProvider.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/JuneauProvider.java b/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/JuneauProvider.java new file mode 100644 index 0000000..b0e54c0 --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/JuneauProvider.java @@ -0,0 +1,96 @@ +// *************************************************************************************************************************** +// * 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.rest.jaxrs; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +import org.apache.juneau.*; +import org.apache.juneau.json.*; +import org.apache.juneau.parser.*; +import org.apache.juneau.rest.*; +import org.apache.juneau.rest.annotation.*; +import org.apache.juneau.serializer.*; +import org.apache.juneau.transform.*; +import org.apache.juneau.xml.*; + +/** + * Annotations applicable to subclasses of {@link BaseProvider}. + * + * <h6 class='topic'>Description</h6> + * <p> + * Used to associate serializers, parsers, filters, and properties with instances of {@link BaseProvider}. + */ +@Documented +@Target(TYPE) +@Retention(RUNTIME) +@Inherited +public @interface JuneauProvider { + + /** + * Provider-level bean filters. + * <p> + * These filters are applied to all serializers and parsers being used by the provider. + * <p> + * If the specified class is an instance of {@link BeanFilterBuilder}, then a filter built from that builder is added. + * Any other classes are wrapped in a {@link InterfaceBeanFilterBuilder} to indicate that subclasses should + * be treated as the specified class type. + */ + Class<?>[] beanFilters() default {}; + + /** + * Provider-level POJO swaps. + * <p> + * These POJO swaps are applied to all serializers and parsers being used by the provider. + * <p> + * If the specified class is an instance of {@link PojoSwap}, then that swap is added. + * Any other classes are wrapped in a {@link SurrogateSwap}. + */ + Class<?>[] pojoSwaps() default {}; + + /** + * Provider-level properties. + * <p> + * Any of the following property names can be specified: + * <ul> + * <li>{@link RestServletContext} + * <li>{@link BeanContext} + * <li>{@link SerializerContext} + * <li>{@link ParserContext} + * <li>{@link JsonSerializerContext} + * <li>{@link XmlSerializerContext} + * <li>{@link XmlParserContext} + * </ul> + * <p> + * Property values will be converted to the appropriate type. + * <p> + * These properties can be augmented/overridden through the {@link RestMethod#properties()} annotation on the REST method. + */ + Property[] properties() default {}; + + /** + * Specifies a list of {@link Serializer} classes to add to the list of serializers available for this provider. + * <p> + * This annotation can only be used on {@link Serializer} classes that have no-arg constructors. + */ + Class<? extends Serializer>[] serializers() default {}; + + /** + * Specifies a list of {@link Parser} classes to add to the list of parsers available for this provider. + * <p> + * This annotation can only be used on {@link Parser} classes that have no-arg constructors. + */ + Class<? extends Parser>[] parsers() default {}; +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/package.html ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/package.html b/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/package.html new file mode 100644 index 0000000..e877328 --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/package.html @@ -0,0 +1,360 @@ +<!DOCTYPE HTML> +<!-- +/*************************************************************************************************************************** + * 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. + * + ***************************************************************************************************************************/ + --> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <style type="text/css"> + /* For viewing in Page Designer */ + @IMPORT url("../../../../../javadoc.css"); + + /* For viewing in REST interface */ + @IMPORT url("../htdocs/javadoc.css"); + body { + margin: 20px; + } + </style> + <script> + /* Replace all @code and @link tags. */ + window.onload = function() { + document.body.innerHTML = document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>'); + document.body.innerHTML = document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, '<code>$3</code>'); + } + </script> +</head> +<body> +<p>JAX-RS / Wink integration components</p> + +<script> + function toggle(x) { + var div = x.nextSibling; + while (div != null && div.nodeType != 1) + div = div.nextSibling; + if (div != null) { + var d = div.style.display; + if (d == 'block' || d == '') { + div.style.display = 'none'; + x.className += " closed"; + } else { + div.style.display = 'block'; + x.className = x.className.replace(/(?:^|\s)closed(?!\S)/g , '' ); + } + } + } +</script> + +<p> + Defines an API and default provides for using Juneau serializers and parsers as JAX-RS providers. +</p> + +<a id='TOC'></a><h5 class='toc'>Table of Contents</h5> +<ol class='toc'> + <li><p><a class='doclink' href='#BaseProvider'>Juneau JAX-RS Provider</a></p> +</ol> + +<!-- ======================================================================================================== --> +<a id="BaseProvider"></a> +<h2 class='topic' onclick='toggle(this)'>1 - Juneau JAX-RS Provider</h2> +<div class='topic'> + <p> + The Juneau framework contains the <code>org.apache.juneau.rest.jaxrs</code> package for performing simple + integration of Juneau serializers and parsers in JAX-RS compliant environments. + </p> + <p> + It should be noted that although some of the functionality of the Juneau Server API is provided through the JAX-RS + integration components, it is not nearly as flexible as using the {@link org.apache.juneau.rest.RestServlet} class directly. + </p> + <p> + What you can do with the Juneau JAX-RS provider classes: + </p> + <ul class='spaced-list'> + <li>Use existing Juneau serializers and parsers for converting streams to POJOs and vis-versa. + <li>Use annotations to specify filters and properties using the {@link org.apache.juneau.rest.annotation.RestMethod} + and {@link org.apache.juneau.rest.jaxrs.JuneauProvider} annotations. + </ul> + <p> + What you can't do with the Juneau JAX-RS provider classes: + </p> + <ul class='spaced-list'> + <li>Specify or override serializers/parsers at the Java class and method levels. + <br>JAX-RS does not provide the capability to use different providers for the same media types + at the class or method levels. + <li>Specify or override filters and properties at the Java class level. + <li>Default stylesheets for the {@link org.apache.juneau.html.HtmlDocSerializer} class. + <br>It will produce HTML, but it won't contain any styles applied. + <br>However, it's possible to specify your own stylesheet using the {@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_cssUrl} property. + <li>The ability to specify HTTP method, headers, and content using GET parameters. + <br>These make debugging REST interfaces using only a browser possible. + <li>Class or method level encoding. + <li>Class or method level guards. + <li>Class or method level converters. + </ul> + + <h6 class='topic'>Juneau JAX-RS Provider API</h6> + <p> + The Juneau JAX-RS provider API consists of the following classes: + </p> + <ul class='spaced-list'> + <li>{@link org.apache.juneau.rest.jaxrs.BaseProvider} - The base provider class that implements the JAX-RS + <code>MessageBodyReader</code> and <code>MessageBodyWriter</code> interfaces. + <li>{@link org.apache.juneau.rest.jaxrs.JuneauProvider} - Annotation that is applied to subclasses of <code>BaseProvider</code> + to specify the serializers/parsers associated with a provider, and optionally filters and properties to + apply to those serializers and parsers. + <li>{@link org.apache.juneau.rest.jaxrs.DefaultProvider} - A default provider that provides the same level + of media type support as the {@link org.apache.juneau.rest.RestServletDefault} class. + </ul> + <p> + For the most part, when using these components, you'll either use the existing <code>DefaultProvider</code> or + <code>JuneauProvider</code> providers, or define your own by subclassing <code>BaseProvider</code>. + + <h6 class='topic'>Example:</h6> + <p> + The <code>juneau_sample.war</code> project contains a sample <code>HelloWorldResource</code> class that + shows how to use the JAX-RS provider. It uses Wink as the JAX-RS implementation. + </p> + <p> + Wink is configured by registering the following servlet in the <code>web.xml</code> file of the web app: + </p> + <p class='bcode'> + <xt><?xml</xt> <xa>version</xa>=<xs>"1.0"</xs> <xa>encoding</xa>=<xs>"UTF-8"</xs><xt>?></xt> + <xt><web-app</xt> <xa>version</xa>=<xs>"2.3"</xs><xt>></xt> + <xt><servlet></xt> + <xt><servlet-name></xt>WinkService<xt></servlet-name></xt> + <xt><servlet-class></xt>org.apache.wink.server.internal.servlet.RestServlet<xt></servlet-class></xt> + <xt><init-param></xt> + <xt><param-name></xt>applicationConfigLocation<xt></param-name></xt> + <xt><param-value></xt>/WEB-INF/wink.cfg<xt></param-value></xt> + <xt></init-param></xt> + <xt></servlet></xt> + <xt><servlet-mapping></xt> + <xt><servlet-name></xt>WinkService<xt></servlet-name></xt> + <xt><url-pattern></xt>/wink/*<xt></url-pattern></xt> + <xt></servlet-mapping></xt> + <xt></web-app></xt> + </p> + <p> + The <code>wink.cfg</code> file lists our default provider and our sample resource: + </p> + <p class='bcode'> + org.apache.juneau.rest.jaxrs.DefaultProvider + com.foo.sample.jaxrs.HelloWorldResource + </p> + <p> + Interestingly, the <code>DefaultProvider</code> itself is a subclass of <code>BaseProvider</code> + with no code at all. It consists of annotations only: + </p> + <p class='bcode'> + <ja>@Provider</ja> + <ja>@Produces</ja>( + <js>"application/json,text/json,"</js>+ <jc>// JsonSerializer</jc> + <js>"application/json+schema,text/json+schema,"</js>+ <jc>// JsonSchemaSerializer</jc> + <js>"text/xml,"</js>+ <jc>// XmlDocSerializer</jc> + <js>"text/xml+schema,"</js>+ <jc>// XmlDocSerializer</jc> + <js>"text/html,"</js>+ <jc>// HtmlDocSerializer</jc> + <js>"application/x-www-form-urlencoded,"</js>+ <jc>// UrlEncodingSerializer</jc> + <js>"text/xml+soap,"</js>+ <jc>// SoapXmlSerializer</jc> + <js>"text/xml+rdf,"</js>+ <jc>// RdfXmlDocSerializer</jc> + <js>"application/x-java-serialized-object"</js> <jc>// JavaSerializedObjectSerializer</jc> + ) + <ja>@Consumes</ja>( + <js>"application/json,text/json,"</js>+ <jc>// JsonParser</jc> + <js>"text/xml,"</js>+ <jc>// XmlParser</jc> + <js>"text/html,"</js>+ <jc>// HtmlParser</jc> + <js>"application/x-www-form-urlencoded"</js> <jc>// UrlEncodingParser</jc> + ) + <ja>@JuneauProvider</ja>( + serializers={ + JsonSerializer.<jk>class</jk>, + JsonSchemaSerializer.<jk>class</jk>, + XmlDocSerializer.<jk>class</jk>, + XmlSchemaDocSerializer.<jk>class</jk>, + HtmlDocSerializer.<jk>class</jk>, + UrlEncodingSerializer.<jk>class</jk>, + SoapXmlSerializer.<jk>class</jk>, + RdfXmlDocSerializer.<jk>class</jk>, + JavaSerializedObjectSerializer.<jk>class</jk> + }, + parsers={ + JsonParser.<jk>class</jk>, + XmlParser.<jk>class</jk>, + HtmlParser.<jk>class</jk>, + UrlEncodingParser.<jk>class</jk> + } + ) + <jk>public final class</jk> DefaultProvider <jk>extends</jk> BaseProvider {} + </p> + <p> + Similarly, if you're defining your own JAX-RS provider, you can do so using annotations only. + </p> + <p> + <p> + Our sample resource is shown below. + In this example, we've specified a <code><ja>@RestMethod</ja></code> annotation on the + getter to show how properties can be overridden on the serializers/parsers at the method level. + This annotation is optional. + </p> + + <p class='bcode'> + <ja>@Path</ja>(<js>"/helloworld"</js>) + <jk>public class</jk> HelloWorldResource { + + <jc>// Our bean message class</jc> + <jk>public static class</jk> Message { + + <jc>// No-arg bean constructor (needed for parsers)</jc> + <jk>public</jk> Message() {} + + <jk>public</jk> Message(String text, String author) { + <jk>this</jk>.text = text; + <jk>this</jk>.author = author; + } + + <jk>public</jk> String text; + <jk>public</jk> String author; + } + + <jk>private static</jk> Message message = <jk>new</jk> Message(<js>"Hello world"</js>, <js>"John Smith"</js>); + + <ja>@GET</ja> + <ja>@Produces</ja>(<js>"*/*"</js>) + <ja>@RestMethod</ja>( <jc>/* Override some properties */</jc> + properties={ + <ja>@Property</ja>(name=SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, value=<js>"true"</js>), + <ja>@Property</ja>(name=JsonSerializerContext.<jsf>LAX_MODE</jsf>, value=<js>"true"</js>) + } + ) + <jk>public</jk> Message getMessage() { + <jk>return</jk> message; + } + + <ja>@PUT</ja> + <ja>@Produces</ja>(<js>"*/*"</js>) + <ja>@Consumes</ja>(<js>"*/*"</js>) + <jk>public</jk> Message replaceMessage(Message message) { + HelloWorldResource.message = message; + <jk>return</jk> message; + } + } + </p> + <p> + When we start up the servlet, we can interact with the resource using cURL. + In these examples, note that the <jsf>SERIALIZER_useIndentation</jsf> and <jsf>LAX_MODE</jsf> settings + cause the output to be readable instead of condensed. + </p> + <p class='bcode'> + C:\>curl.exe -H "Accept: text/json" -X GET http://localhost:9080/sample/wink/helloworld + <ja>{ + text:"Hello world", + author:"John Smith" + }</ja> + </p> + <p class='bcode'> + C:\>curl.exe -H "Accept: text/html" -X GET http://localhost:9080/sample/wink/helloworld + <ja><html> + <head> + </head> + <body> + <table type="object"> + <tr> + <th> + <string>key</string> + </th> + <th> + <string>value</string> + </th> + </tr> + <tr> + <td> + <string>text</string> + </td> + <td> + <string>Hello world</string> + </td> + </tr> + <tr> + <td> + <string>author</string> + </td> + <td> + <string>John Smith</string> + </td> + </tr> + </table> + </body> + </html></ja> + </p> + <p class='bcode'> + C:\>curl.exe -H "Accept: text/xml" -X GET http://localhost:9080/sample/wink/helloworld + <ja><?xml version="1.0" encoding="UTF-8"?> + <object> + <text>Hello world</text> + <author>John Smith</author> + </object></ja> + </p> + <p class='bcode'> + C:\>curl.exe -H "Accept: application/x-www-form-urlencoded" -X GET http://localhost:9080/sample/wink/helloworld + <ja>text='Hello+world'&author='John+Smith'</ja> + </p> + <p class='bcode'> + C:\>curl.exe -H "Accept: text/xml+schema" -X GET http://localhost:9080/sample/wink/helloworld + <ja><?xml version="1.0" encoding="UTF-8"?> + <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <xs:element name="object" nillable="true"> + <xs:complexType> + <xs:sequence minOccurs="0" maxOccurs="unbounded"> + <xs:element name="text" type="xs:string" nillable="true" minOccurs="0"/> + <xs:element name="author" type="xs:string" nillable="true" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="null"/> + </xs:schema></ja> + </p> + <p class='bcode'> + C:\>curl.exe -H "Accept: application/x-java-serialized-object" -X GET http://localhost:9080/sample/wink/helloworld + <ja>detailMessaget âLjava/lang/String;[ ption(Vx ÏÃ¥â¬5â» xr âjava.io.ObjectStreamExceptiondâΣkì9âââ» xr â¼java.io.IOExcept + stackTracet â²[Ljava/lang/StackTraceElement;xpq t /org.apache.juneau.samples.jaxrs.HelloWorldResource$Messageur â²[Ljava.lang.Sta + lineNumberL â«declaringClassq ~ â LfileNameq ~ â L + methodNameq ~ â xp â¦Ã¡t âjava.io.ObjectOutputStreamt â¨ObjectOutputStream.javat âwriteObject0sq ~ â âº[t âjava.io.Obje + 3org.apache.juneau.serializer.OutputStreamSerializert âOutputStreamSerializer.javat serializesq ~ â ^t &com.ib + &t /org.apache.wink.server.handlers.AbstractHandlert ¶AbstractHandler.javat â«handleResponsesq ~ â ât 5org.apache. + sq ~ â Ct 5org.apache.wink.server.handlers.AbstractHandlersChaint âAbstractHandlersChain.javat doChainsq ~ â 't + â handlesq ~ â â¬t 5org.apache.wink.server.handlers.ResponseHandlersChaint âResponseHandlersChain.javat â handlesq ~ + â«handleResponsesq ~ â ât 5org.apache.wink.server.handlers.ResponseHandlersChaint âResponseHandlersChain.javat â ha + tHandlersChain.javat doChainsq ~ â Zt -org.apache.wink.server.internal.log.Responsest â«Responses.javat â«handleResp + eHandlersChain.javat â handlesq ~ â Ct 5org.apache.wink.server.handlers.AbstractHandlersChaint âAbstractHandlersCha + handleRequestsq ~ â |t 3org.apache.wink.server.internal.servlet.RestServlett âºRestServlet.javat servicesq ~ â â»Â£t + handleRequestsq ~ â ât -com.ibm.ws.webcontainer.channel.WCChannelLinkt âWCChannelLink.javat â£readysq ~ â âºât 4com + âºhandleNewRequestsq ~ â âº1t 4com.ibm.ws.http.channel.inbound.impl.HttpInboundLinkt ¶HttpInboundLink.javat â«process + nnectionInitialReadCallback.javat ¶sendToDiscriminatorssq ~ â qt <com.ibm.ws.tcp.channel.impl.NewConnectionInitial + ât $com.ibm.io.async.AbstractAsyncFuturet âAbstractAsyncFuture.javat â«invokeCallbacksq ~ â Ãt #com.ibm.io.async. + t âResultHandler.javatcompletesq ~ â â¥t â²com.ibm.io.async.ResultHandlert âResultHandler.javat â¬runEventProcessingLo + on: java.io.NotSerializableException: org.apache.juneau.samples.jaxrs.HelloWorldResource$Message</ja> + </p> + <p> + The following shows the PUT method being invoked. + In this case, we're passing in the new bean as a JSON object. + Also notice how the response is in standard condensed JSON since we did not override any properties on the REST method. + </p> + <p class='bcode'> + C:\>curl.exe -H "Content-Type: text/json" -H "Accept: text/json" -d "{text:'Hello again',author:'Jane Doe'}" + -X PUT http://localhost:9080/sample/wink/helloworld + <ja>{"text":"Hello again","author":"Jane Doe"}</ja> + </p> +</div> + +</body> +</html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/rdf/DefaultJenaProvider.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/rdf/DefaultJenaProvider.java b/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/rdf/DefaultJenaProvider.java new file mode 100644 index 0000000..e4208c9 --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/rdf/DefaultJenaProvider.java @@ -0,0 +1,91 @@ +// *************************************************************************************************************************** +// * 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.rest.jaxrs.rdf; + +import javax.ws.rs.*; +import javax.ws.rs.ext.*; + +import org.apache.juneau.html.*; +import org.apache.juneau.jena.*; +import org.apache.juneau.jso.*; +import org.apache.juneau.json.*; +import org.apache.juneau.rest.jaxrs.*; +import org.apache.juneau.rest.jena.*; +import org.apache.juneau.soap.*; +import org.apache.juneau.urlencoding.*; +import org.apache.juneau.xml.*; + +/** + * JAX-RS provider for the same serialize/parse support provided by the {@link RestServletJenaDefault} class. + */ +@Provider +@Produces({ + "application/json", "text/json", // JsonSerializer + "application/json+simple","text/json+simple", // JsonSerializer.Simple + "application/json+schema","text/json+schema", // JsonSchemaSerializer + "text/xml", // XmlDocSerializer + "text/xml+simple", // XmlDocSerializer.Simple + "text/xml+schema", // XmlSchemaDocSerializer + "text/html", // HtmlDocSerializer + "application/x-www-form-urlencoded", // UrlEncodingSerializer + "text/xml+soap", // SoapXmlSerializer + "text/xml+rdf", // RdfSerializer.Xml + "text/xml+rdf+abbrev", // RdfSerializer.XmlAbbrev + "text/n-triple", // RdfSerializer.NTriple + "text/turtle", // RdfSerializer.Turtle + "text/n3", // RdfSerializer.N3 + "application/x-java-serialized-object" // JavaSerializedObjectSerializer +}) +@Consumes({ + "application/json", "text/json", // JsonParser + "text/xml", // XmlParser + "text/html", // HtmlParser + "application/x-www-form-urlencoded", // UrlEncodingParser + "text/xml+rdf", // RdfParser.Xml + "text/n-triple", // RdfParser.NTriple + "text/turtle", // RdfParser.Turtle + "text/n3", // RdfParser.N3 + "application/x-java-serialized-object" // JavaSerializedObjectParser +}) +@JuneauProvider( + serializers={ + JsonSerializer.class, + JsonSerializer.Simple.class, + JsonSchemaSerializer.class, + XmlDocSerializer.class, + XmlDocSerializer.Simple.class, + XmlSchemaDocSerializer.class, + HtmlDocSerializer.class, + UrlEncodingSerializer.class, + SoapXmlSerializer.class, + RdfSerializer.Xml.class, + RdfSerializer.XmlAbbrev.class, + RdfSerializer.NTriple.class, + RdfSerializer.Turtle.class, + RdfSerializer.N3.class, + JavaSerializedObjectSerializer.class + }, + parsers={ + JsonParser.class, + XmlParser.class, + HtmlParser.class, + UrlEncodingParser.class, + RdfParser.Xml.class, + RdfParser.NTriple.class, + RdfParser.Turtle.class, + RdfParser.N3.class, + JavaSerializedObjectParser.class, + } +) +public final class DefaultJenaProvider extends BaseProvider {} + http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/rdf/package.html ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/rdf/package.html b/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/rdf/package.html new file mode 100644 index 0000000..6bb6d97 --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/jaxrs/rdf/package.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<!-- +/*************************************************************************************************************************** + * 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. + * + ***************************************************************************************************************************/ + --> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <style type="text/css"> + /* For viewing in Page Designer */ + @IMPORT url("../../../../../../javadoc.css"); + + /* For viewing in REST interface */ + @IMPORT url("../htdocs/javadoc.css"); + body { + margin: 20px; + } + </style> +</head> +<body> +<p>JAX-RS / Wink integration components with RDF support</p> +</body> +</html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/jena/RestServletJenaDefault.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/jena/RestServletJenaDefault.java b/juneau-rest/src/main/java/org/apache/juneau/rest/jena/RestServletJenaDefault.java new file mode 100644 index 0000000..963a258 --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/jena/RestServletJenaDefault.java @@ -0,0 +1,272 @@ +// *************************************************************************************************************************** +// * 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.rest.jena; + +import static org.apache.juneau.html.HtmlDocSerializerContext.*; +import static org.apache.juneau.rest.RestServletContext.*; + +import org.apache.juneau.dto.swagger.*; +import org.apache.juneau.html.*; +import org.apache.juneau.jena.*; +import org.apache.juneau.jso.*; +import org.apache.juneau.json.*; +import org.apache.juneau.msgpack.*; +import org.apache.juneau.plaintext.*; +import org.apache.juneau.rest.*; +import org.apache.juneau.rest.annotation.*; +import org.apache.juneau.soap.*; +import org.apache.juneau.urlencoding.*; +import org.apache.juneau.xml.*; + +/** + * Subclass of {@link RestServlet} with default sets of serializers and parsers that include RDF support. + * <p> + * Extends the {@link org.apache.juneau.rest.RestServletDefault} class with additional RDF support. + * <p> + * <p> + * Supports the following request <code>Accept</code> header values with the resulting response <code>Content-Type</code>: + * </p> + * <table class='styled'> + * <tr> + * <th>Accept</th> + * <th>Content-Type</th> + * <th>Serializer</th> + * </tr> + * <tr> + * <td class='code'>application/json<br>text/json</td> + * <td class='code'>application/json</td> + * <td>{@link JsonSerializer}</td> + * </tr> + * <tr> + * <td class='code'>application/json+simple<br>text/json+simple</td> + * <td class='code'>application/json</td> + * <td>{@link org.apache.juneau.json.JsonSerializer.Simple}</td> + * </tr> + * <td class='code'>application/json+schema<br>text/json+schema</td> + * <td class='code'>application/json</td> + * <td>{@link JsonSchemaSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/xml</td> + * <td class='code'>text/xml</td> + * <td>{@link XmlDocSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/xml+schema</td> + * <td class='code'>text/xml</td> + * <td>{@link XmlSchemaDocSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/html</td> + * <td class='code'>text/html</td> + * <td>{@link HtmlDocSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/html+stripped</td> + * <td class='code'>text/html</td> + * <td>{@link HtmlStrippedDocSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/uon</td> + * <td class='code'>text/uon</td> + * <td>{@link UonSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/uon-simple</td> + * <td class='code'>text/uon</td> + * <td>{@link org.apache.juneau.urlencoding.UonSerializer.Simple}</td> + * </tr> + * <tr> + * <td class='code'>application/x-www-form-urlencoded</td> + * <td class='code'>application/x-www-form-urlencoded</td> + * <td>{@link UrlEncodingSerializer}</td> + * </tr> + * <tr> + * <td class='code'>application/x-www-form-urlencoded-simple</td> + * <td class='code'>application/x-www-form-urlencoded</td> + * <td>{@link org.apache.juneau.urlencoding.UrlEncodingSerializer.Simple}</td> + * </tr> + * <tr> + * <td class='code'>text/xml+soap</td> + * <td class='code'>text/xml</td> + * <td>{@link SoapXmlSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/plain</td> + * <td class='code'>text/plain</td> + * <td>{@link PlainTextSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/plain</td> + * <td class='code'>text/plain</td> + * <td>{@link PlainTextSerializer}</td> + * </tr> + * <tr> + * <td class='code'>application/x-java-serialized-object</td> + * <td class='code'>application/x-java-serialized-object</td> + * <td>{@link JavaSerializedObjectSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/xml+rdf</td> + * <td class='code'>text/xml+rdf</td> + * <td>{@link org.apache.juneau.jena.RdfSerializer.Xml}</td> + * </tr> + * <tr> + * <td class='code'>text/xml+rdf+abbrev</td> + * <td class='code'>text/xml+rdf</td> + * <td>{@link org.apache.juneau.jena.RdfSerializer.XmlAbbrev}</td> + * </tr> + * <tr> + * <td class='code'>text/n3</td> + * <td class='code'>text/n3</td> + * <td>{@link org.apache.juneau.jena.RdfSerializer.N3}</td> + * </tr> + * <tr> + * <td class='code'>text/n-triple</td> + * <td class='code'>text/n-triple</td> + * <td>{@link org.apache.juneau.jena.RdfSerializer.NTriple}</td> + * </tr> + * <tr> + * <td class='code'>text/turtle</td> + * <td class='code'>text/turtle</td> + * <td>{@link org.apache.juneau.jena.RdfSerializer.Turtle}</td> + * </tr> + * </table> + * <p> + * Supports the following request <code>Content-Type</code> header values: + * </p> + * <table class='styled'> + * <tr> + * <th>Content-Type</th> + * <th>Parser</th> + * </tr> + * <tr> + * <td class='code'>application/json<br>text/json</td> + * <td>{@link JsonParser}</td> + * </tr> + * <tr> + * <td class='code'>text/xml<br>application/xml</td> + * <td>{@link XmlParser}</td> + * </tr> + * <tr> + * <td class='code'>text/html<br>text/html+stripped</td> + * <td>{@link HtmlParser}</td> + * </tr> + * <tr> + * <td class='code'>text/uon</td> + * <td>{@link UonParser}</td> + * </tr> + * <tr> + * <td class='code'>application/x-www-form-urlencoded</td> + * <td>{@link UrlEncodingParser}</td> + * </tr> + * <tr> + * <td class='code'>text/plain</td> + * <td>{@link PlainTextParser}</td> + * </tr> + * <tr> + * <td class='code'>text/xml+rdf</td> + * <td>{@link org.apache.juneau.jena.RdfParser.Xml}</td> + * </tr> + * <tr> + * <td class='code'>text/n3</td> + * <td>{@link org.apache.juneau.jena.RdfParser.N3}</td> + * </tr> + * <tr> + * <td class='code'>text/n-triple</td> + * <td>{@link org.apache.juneau.jena.RdfParser.NTriple}</td> + * </tr> + * <tr> + * <td class='code'>text/turtle</td> + * <td>{@link org.apache.juneau.jena.RdfParser.Turtle}</td> + * </tr> + * </table> + * <p> + * Note that the list of serializers and parsers can be appended to using the {@link RestResource#serializers() @RestResource.serializers()} + * and {@link RestResource#parsers() @RestResource.parsers()} annotations on subclasses. + * </p> + */ +@RestResource( + serializers={ + HtmlDocSerializer.class, // HTML must be listed first because Internet Explore does not include text/html in their Accept header. + HtmlStrippedDocSerializer.class, + HtmlSchemaDocSerializer.class, + JsonSerializer.class, + JsonSerializer.Simple.class, + JsonSchemaSerializer.class, + XmlDocSerializer.class, + XmlDocSerializer.Simple.class, + XmlSchemaDocSerializer.class, + UonSerializer.class, + UonSerializer.Simple.class, + UrlEncodingSerializer.class, + UrlEncodingSerializer.Simple.class, + MsgPackSerializer.class, + SoapXmlSerializer.class, + JavaSerializedObjectSerializer.class, + PlainTextSerializer.class, + RdfSerializer.Xml.class, + RdfSerializer.XmlAbbrev.class, + RdfSerializer.N3.class, + RdfSerializer.NTriple.class, + RdfSerializer.Turtle.class, + }, + parsers={ + JsonParser.class, + XmlParser.class, + HtmlParser.class, + UonParser.class, + UrlEncodingParser.class, + MsgPackParser.class, + RdfParser.Xml.class, + RdfParser.N3.class, + RdfParser.NTriple.class, + RdfParser.Turtle.class + }, + properties={ + // Allow &method parameter on safe HTTP methods. + @Property(name=REST_allowMethodParam, value="OPTIONS"), + // Provide a default title on HTML pages. + @Property(name=HTMLDOC_title, value="$R{servletTitle}"), + // Provide a default description on HTML pages. + @Property(name=HTMLDOC_description, value="$R{servletDescription}") + }, + stylesheet="styles/juneau.css", + favicon="juneau.ico", + staticFiles="{htdocs:'htdocs'}" +) +public abstract class RestServletJenaDefault extends RestServlet { + private static final long serialVersionUID = 1L; + + /** + * [OPTIONS /*] - Show resource options. + * + * @param req The HTTP request. + * @return The bean containing the contents of the OPTIONS page. + */ + @RestMethod(name="OPTIONS", path="/*", + properties={ + @Property(name=HTMLDOC_links, value="{back:'$R{servletURI}'}"), + @Property(name=HTMLDOC_description, value="Resource options") + }, + description="Resource options" + ) + public Swagger getOptions(RestRequest req) { + return req.getSwagger(); + } + + @Override /* RestServlet */ + public boolean hasOptionsPage() { + return true; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/jena/RestServletJenaGroupDefault.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/jena/RestServletJenaGroupDefault.java b/juneau-rest/src/main/java/org/apache/juneau/rest/jena/RestServletJenaGroupDefault.java new file mode 100644 index 0000000..5ef37be --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/jena/RestServletJenaGroupDefault.java @@ -0,0 +1,41 @@ +// *************************************************************************************************************************** +// * 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.rest.jena; + +import org.apache.juneau.rest.*; +import org.apache.juneau.rest.annotation.*; +import org.apache.juneau.rest.labels.*; + +/** + * Specialized subclass of {@link RestServletJenaDefault} for showing "group" pages. + * <p> + * Group pages consist of simple lists of child resource URLs and their labels. + * They're meant to be used as jumping-off points for child resources. + * <p> + * Child resources are specified using the {@link RestResource#children()} annotation. + */ +@RestResource() +public abstract class RestServletJenaGroupDefault extends RestServletJenaDefault { + private static final long serialVersionUID = 1L; + + /** + * [GET /] - Get child resources. + * + * @param req The HTTP request + * @return The bean containing links to the child resources. + */ + @RestMethod(name="GET", path="/", description="Child resources") + public ChildResourceDescriptions getChildren(RestRequest req) { + return new ChildResourceDescriptions(this, req); + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/jena/package.html ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/jena/package.html b/juneau-rest/src/main/java/org/apache/juneau/rest/jena/package.html new file mode 100644 index 0000000..3fe0832 --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/jena/package.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<!-- +/*************************************************************************************************************************** + * 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. + * + ***************************************************************************************************************************/ + --> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <style type="text/css"> + /* For viewing in Page Designer */ + @IMPORT url("../../../../../javadoc.css"); + + /* For viewing in REST interface */ + @IMPORT url("../htdocs/javadoc.css"); + body { + margin: 20px; + } + </style> + <script> + /* Replace all @code and @link tags. */ + window.onload = function() { + document.body.innerHTML = document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>'); + document.body.innerHTML = document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, '<code>$3</code>'); + } + </script> +</head> +<body> +<p>RET servlet API with Jena components</p> + +<p> + Contains predefined instances of REST API classes with Jena support included. +</p> + + +</body> +</html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/juneau.ico ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/juneau.ico b/juneau-rest/src/main/java/org/apache/juneau/rest/juneau.ico new file mode 100644 index 0000000..737f40a Binary files /dev/null and b/juneau-rest/src/main/java/org/apache/juneau/rest/juneau.ico differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/labels/BeanDescription.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/labels/BeanDescription.java b/juneau-rest/src/main/java/org/apache/juneau/rest/labels/BeanDescription.java new file mode 100644 index 0000000..08565eb --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/labels/BeanDescription.java @@ -0,0 +1,70 @@ +// *************************************************************************************************************************** +// * 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.rest.labels; + +import org.apache.juneau.*; +import org.apache.juneau.annotation.*; + +/** + * Simple serializable bean description. + * <p> + * Given a particular class type, this serializes the class into + * the fully-qualified class name and the properties associated with the class. + * <p> + * Useful for rendering simple information about a bean during REST OPTIONS requests. + */ +@Bean(properties="type,properties") +public final class BeanDescription { + + /** The bean class type. */ + public String type; + + /** The bean properties. */ + public BeanPropertyDescription[] properties; + + /** + * Constructor + * @param c The bean class type. + */ + public BeanDescription(Class<?> c) { + type = c.getName(); + BeanMeta<?> bm = BeanContext.DEFAULT.getBeanMeta(c); + properties = new BeanPropertyDescription[bm.getPropertyMetas().size()]; + int i = 0; + for (BeanPropertyMeta pm : bm.getPropertyMetas()) + properties[i++] = new BeanPropertyDescription(pm.getName(), pm.getClassMeta()); + } + + /** + * Information about a bean property. + */ + public static class BeanPropertyDescription { + + /** The bean property name. */ + public String name; + + /** The bean property filtered class type. */ + public String type; + + /** + * Constructor. + * + * @param name The bean property name. + * @param type The bean property class type. + */ + public BeanPropertyDescription(String name, ClassMeta<?> type) { + this.name = name; + this.type = type.getSerializedClassMeta().toString(); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/labels/ChildResourceDescriptions.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/labels/ChildResourceDescriptions.java b/juneau-rest/src/main/java/org/apache/juneau/rest/labels/ChildResourceDescriptions.java new file mode 100644 index 0000000..63ba284 --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/labels/ChildResourceDescriptions.java @@ -0,0 +1,61 @@ +// *************************************************************************************************************************** +// * 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.rest.labels; + +import java.util.*; + +import org.apache.juneau.rest.*; + +/** + * A POJO structure that describes the list of child resources associated with a resource. + * <p> + * Typically used in top-level GET methods of router resources to render a list of + * available child resources. + */ +public class ChildResourceDescriptions extends LinkedList<ResourceDescription> { + + private static final long serialVersionUID = 1L; + + /** + * Constructor. + * + * @param servlet The servlet that this bean describes. + * @param req The HTTP servlet request. + */ + public ChildResourceDescriptions(RestServlet servlet, RestRequest req) { + this(servlet, req, false); + } + + /** + * Constructor. + * + * @param servlet The servlet that this bean describes. + * @param req The HTTP servlet request. + * @param sort If <jk>true</jk>, list will be ordered by name alphabetically. + * Default is to maintain the order as specified in the annotation. + */ + public ChildResourceDescriptions(RestServlet servlet, RestRequest req, boolean sort) { + String uri = req.getTrimmedRequestURI(); + for (Map.Entry<String,RestServlet> e : servlet.getChildResources().entrySet()) + add(new ResourceDescription(uri, e.getKey(), e.getValue().getTitle(req))); + if (sort) + Collections.sort(this); + } + + /** + * Bean constructor. + */ + public ChildResourceDescriptions() { + super(); + } +}
