diff --git a/dna-common/src/main/java/org/jboss/dna/common/util/Base64.java b/dna-common/src/main/java/org/jboss/dna/common/util/Base64.java index f804900..af95120 100644 --- a/dna-common/src/main/java/org/jboss/dna/common/util/Base64.java +++ b/dna-common/src/main/java/org/jboss/dna/common/util/Base64.java @@ -671,6 +671,82 @@ public class Base64 { } + /** + * Encodes content of the supplied InputStream into Base64 notation. Does not GZip-compress data. + * + * @param source The data to convert + * @return the encoded bytes + */ + public static String encode( java.io.InputStream source ) { + return encode(source, NO_OPTIONS); + } + + /** + * Encodes the content of the supplied InputStream into Base64 notation. + *

+ * Valid options: + * + *

+     *   GZIP: gzip-compresses object before encoding it.
+     *   DONT_BREAK_LINES: don't break lines at 76 characters
+     *     <i>Note: Technically, this makes your encoding non-compliant.</i>
+     * 
+ *

+ * Example: encodeBytes( myData, Base64.GZIP ) or + *

+ * Example: encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES ) + * + * @param source The data to convert + * @param options Specified options- the alphabet type is pulled from this (standard, url-safe, ordered) + * @return the encoded bytes + * @see Base64#GZIP + * @see Base64#DONT_BREAK_LINES + */ + public static String encode( java.io.InputStream source, + int options ) { + java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(); + Base64.OutputStream b64os = new Base64.OutputStream(baos, ENCODE | options); + BufferedInputStream input = new BufferedInputStream(source); + java.io.OutputStream output = b64os; + + boolean error = false; + try { + if ((options & GZIP) == GZIP) { + output = new java.util.zip.GZIPOutputStream(output); + } + int numRead = 0; + byte[] buffer = new byte[1024]; + while ((numRead = input.read(buffer)) > -1) { + output.write(buffer, 0, numRead); + } + output.close(); + } catch (IOException e) { + error = true; + throw new SystemFailureException(e); // error using reading from byte array! + } finally { + try { + input.close(); + } catch (IOException e) { + if (!error) new SystemFailureException(e); // error closing input stream + } finally { + if (output != null) { + try { + output.close(); + } catch (IOException e) { + if (!error) new SystemFailureException(e); // error closing streams over byte array! + } + } + } + } + + // Return value according to relevant encoding. + try { + return new String(baos.toByteArray(), PREFERRED_ENCODING); + } catch (java.io.UnsupportedEncodingException uue) { + return new String(baos.toByteArray()); + } + } + /* ******** D E C O D I N G M E T H O D S ******** */ /** diff --git a/extensions/dna-web-jcr-rest/src/main/java/org/jboss/dna/web/jcr/rest/JcrResources.java b/extensions/dna-web-jcr-rest/src/main/java/org/jboss/dna/web/jcr/rest/JcrResources.java index e446589..45ce963 100644 --- a/extensions/dna-web-jcr-rest/src/main/java/org/jboss/dna/web/jcr/rest/JcrResources.java +++ b/extensions/dna-web-jcr-rest/src/main/java/org/jboss/dna/web/jcr/rest/JcrResources.java @@ -24,6 +24,7 @@ package org.jboss.dna.web.jcr.rest; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -38,6 +39,7 @@ import javax.jcr.NodeIterator; import javax.jcr.PathNotFoundException; import javax.jcr.Property; import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.Value; @@ -64,6 +66,7 @@ import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.jboss.dna.common.text.UrlEncoder; +import org.jboss.dna.common.util.Base64; import org.jboss.dna.web.jcr.rest.model.RepositoryEntry; import org.jboss.dna.web.jcr.rest.model.WorkspaceEntry; import org.jboss.resteasy.spi.NotFoundException; @@ -269,12 +272,41 @@ public class JcrResources { if (property.getDefinition().isMultiple()) { Value[] values = property.getValues(); List list = new ArrayList(values.length); - for (int i = 0; i < values.length; i++) { - list.add(values[i].getString()); + for (Value value : values) { + list.add(jsonStringFor(value)); } return new JSONArray(list).toString(); } - return JSONObject.quote(property.getValue().getString()); + return JSONObject.quote(jsonStringFor(property.getValue())); + } + + /** + * Return the JSON-compatible string representation of the given property value. If the value is a {@link PropertyType#BINARY + * binary} value, then this method returns the Base-64 encoding of that value. Otherwise, it just returns the string + * representation of the value. + * + * @param value the property value; may not be null + * @return the string representation of the value + * @throws RepositoryException if there is a problem accessing the value + */ + private String jsonStringFor( Value value ) throws RepositoryException { + if (value.getType() == PropertyType.BINARY) { + // Encode the binary value in Base64 ... + InputStream stream = value.getStream(); + try { + return Base64.encode(stream); + } finally { + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + // Error accessing the value, so throw this ... + throw new RepositoryException(e); + } + } + } + } + return value.getString(); } /**