I've created a modification to allow XML to be passed in instead of read from the filesystem
here is the patch:
### Eclipse Workspace Patch 1.0 #P hypergraph Index: source/hypergraph/graphApi/io/SAXReader.java =================================================================== RCS file: /cvsroot/hypergraph/hypergraph/source/hypergraph/graphApi/io/SAXReader.java,v retrieving revision 1.2 diff -u -r1.2 SAXReader.java --- source/hypergraph/graphApi/io/SAXReader.java 23 Oct 2005 17:20:12 -0000 1.2 +++ source/hypergraph/graphApi/io/SAXReader.java 4 Dec 2008 21:49:44 -0000 @@ -21,6 +21,9 @@
package hypergraph.graphApi.io;
+import hypergraph.graphApi.Graph; +import hypergraph.graphApi.GraphSystem; + import java.io.FileNotFoundException; import java.io.IOException; import java.net.URL; @@ -29,13 +32,13 @@ import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory;
+import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; import org.xml.sax.XMLReader;
-import hypergraph.graphApi.Graph; -import hypergraph.graphApi.GraphSystem; - /** * @author Jens Kanschik * @@ -55,6 +58,12 @@ inputSource = new InputSource(filename); createLexicalHandler(); } + + public SAXReader(GraphSystem graphSystem, InputSource content) throws FileNotFoundException, IOException{ + this.graphSystem = graphSystem; + inputSource = content; + createLexicalHandler(); + } public SAXReader(GraphSystem graphSystem, URL url) throws IOException { this.graphSystem = graphSystem; inputSource = new InputSource(url.openStream()); @@ -83,12 +92,29 @@ return graph; } public Graph parse() throws SAXException, IOException, ParserConfigurationException { - SAXParserFactory parserFactory = SAXParserFactory.newInstance(); + return parse(null); + } + public Graph parse(final InputSource dtd) throws ParserConfigurationException, SAXException, + SAXNotRecognizedException, SAXNotSupportedException, IOException { + SAXParserFactory parserFactory = SAXParserFactory.newInstance(); SAXParser parser = parserFactory.newSAXParser(); reader = parser.getXMLReader(); - lexicalHandler.setSAXReader(this); + if (dtd != null) { + reader.setEntityResolver(new EntityResolver() { + @Override + public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { + if (systemId.indexOf("GraphXML.dtd") >= 0) { + return dtd; + } else { + return null; + } + } + + }); + } + lexicalHandler.setSAXReader(this); reader.setProperty("http://xml.org/sax/properties/lexical-handler", lexicalHandler); reader.parse(inputSource); return getGraph(); - } + } } Index: source/hypergraph/applications/hexplorer/DynamicXmlHExplorerApplet.java =================================================================== RCS file: source/hypergraph/applications/hexplorer/DynamicXmlHExplorerApplet.java diff -N source/hypergraph/applications/hexplorer/DynamicXmlHExplorerApplet.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ source/hypergraph/applications/hexplorer/DynamicXmlHExplorerApplet.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2003 Jens Kanschik, + * mail : jensKanschik@users.sourceforge.net + * + * Part of <hypergraph>, an open source project at sourceforge.net + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package hypergraph.applications.hexplorer; + + +import hypergraph.graphApi.Graph; +import hypergraph.graphApi.GraphSystem; +import hypergraph.graphApi.GraphSystemFactory; +import hypergraph.graphApi.Node; +import hypergraph.graphApi.algorithms.GraphUtilities; +import hypergraph.graphApi.io.GraphWriter; +import hypergraph.graphApi.io.GraphXMLWriter; +import hypergraph.graphApi.io.SAXReader; +import hypergraph.visualnet.ArrowLineRenderer; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.URL; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import javax.swing.JApplet; +import javax.swing.JOptionPane; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * @author Jens Kanschik + * + * To change the template for this generated type comment go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +public class DynamicXmlHExplorerApplet extends JApplet { + private static byte[] dtdbytes; + private static final String zipDtd = "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"; + private static byte[] getDtdBytes() throws IOException { + return dtdbytes == null ? dtdbytes = StringZip.unzipBytes(zipDtd) :dtdbytes; + } + + /** Stores the graph that the applet shows. */ + private GraphPanel graphPanel; + + public GraphPanel getGraphPanel() { + return graphPanel; + } + /**@inheritDoc */ + public void init() { + GraphSystem graphSystem = null; + try { + graphSystem = GraphSystemFactory.createGraphSystem("hypergraph.graph.GraphSystemImpl", null); + } catch (Exception e) { + e.printStackTrace(); + System.exit(8); + } + Graph graph = null; + try { + InputSource source = createInput(StringZip + .unzipBytes(getParameter("zipcontent"))); + SAXReader reader = new SAXReader(graphSystem, source); + ContentHandlerFactory ch = new ContentHandlerFactory(); + ch.setBaseUrl(getCodeBase()); + reader.setContentHandlerFactory(ch); + graph = reader.parse(createInput(getDtdBytes())); + } catch (SAXException saxe) { + JOptionPane.showMessageDialog(null, + "Error while parsing dynamic xml. \n" + + "Exception : " + saxe + ". \n" + + "Start applet with default graph", "Parsing error", JOptionPane.ERROR_MESSAGE); + System.out.println("Exception : " + saxe); + saxe.getException().printStackTrace(); + saxe.printStackTrace(System.out); + } catch (Exception e) { + JOptionPane.showMessageDialog(null, + "General error while reading dynamic xml. \n" + + "Exception : " + e + ". \n" + + "Start applet with default graph", "General error", JOptionPane.ERROR_MESSAGE); + System.out.println("Exception : " + e); + e.printStackTrace(System.out); + } + + if (graph == null) { + graph = GraphUtilities.createTree(graphSystem, 2, 3); + } + + graphPanel = new GraphPanel(graph, this); + String file = getParameter("properties"); + URL url = null; + if (file != null) + try { + url = new URL(getCodeBase(), file); + graphPanel.loadProperties(url.openStream()); + } catch (FileNotFoundException fnfe) { + JOptionPane.showMessageDialog(null, + "Could not find propertyfile " + url.getFile() + ". \n" + + "Start applet with default properties", "File not found", JOptionPane.ERROR_MESSAGE); + } catch (Exception e) { + JOptionPane.showMessageDialog(null, + "General error while reading file " + url.getFile() + ". \n" + + "Exception : " + e + ". \n" + + "Start applet with default properties", "General error", JOptionPane.ERROR_MESSAGE); + System.out.println("Exception : " + e); + e.printStackTrace(System.out); + } + + String center = getParameter("center"); + if (center != null) { + Node n = (Node) graph.getElement(center); + if (n != null) + graphPanel.centerNode(n); + } + graphPanel.setLineRenderer(new ArrowLineRenderer()); + + getContentPane().add(graphPanel); + } + + public String getGraphXML() { + try { + OutputStream os = new ByteArrayOutputStream(); + GraphWriter graphWriter = new GraphXMLWriter(new OutputStreamWriter(os)); + graphWriter.write(getGraphPanel().getGraph()); + return os.toString(); + } catch (IOException ioe) { + ioe.printStackTrace(); + return ioe.toString(); + } + } + + private InputSource createInput(byte[] unzipBytes) { + return new InputSource(new ByteArrayInputStream(unzipBytes)); + } +} + +class StringZip { + // map 6-bit nibbles into base 64 characters + private static char[] map1 = new char[64]; + static { + int i = 0; + for (char c = 'A'; c <= 'Z'; c++) + map1[i++] = c; + for (char c = 'a'; c <= 'z'; c++) + map1[i++] = c; + for (char c = '0'; c <= '9'; c++) + map1[i++] = c; + map1[i++] = '+'; + map1[i++] = '/'; + } + + // Mapping table from Base64 characters to 6-bit nibbles. + private static byte[] map2 = new byte[128]; + static { + for (int i = 0; i < map2.length; i++) + map2[i] = -1; + for (int i = 0; i < 64; i++) + map2[map1[i]] = (byte) i; + } + + public static String zip(String input) throws IOException { + return encode64(zip(input.getBytes())); + } + + public static String unzip(String input) throws IOException { + return new String(unzipBytes(input)); + } + + public static byte[] unzipBytes(String input) throws IOException { + return unzip(decode64(input)); + } + + private static byte[] unzip(byte[] zipped) throws IOException { + // TODO Auto-generated method stub + InputStream input = new GZIPInputStream(new ByteArrayInputStream(zipped)); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output); + input.close(); + output.close(); + return output.toByteArray(); + } + + private static byte[] zip(byte[] unzipped) throws IOException { + InputStream input = new ByteArrayInputStream(unzipped); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + GZIPOutputStream zipout = new GZIPOutputStream(output); + copy(input, zipout); + input.close(); + zipout.finish(); + zipout.close(); + return output.toByteArray(); + } + + private static void copy(InputStream input, OutputStream output) throws IOException { + byte[] buf = new byte[1024]; + int len; + while ((len = input.read(buf)) > 0) { + output.write(buf, 0, len); + } + output.flush(); + } + + public static String encode64(byte[] in) { + int iLen = in.length; + int oDataLen = (iLen * 4 + 2) / 3; // output length without padding + int oLen = ((iLen + 2) / 3) * 4; // output length including padding + char[] out = new char[oLen]; + int ip = 0; + int op = 0; + while (ip < iLen) { + int i0 = in[ip++] & 0xff; + int i1 = ip < iLen ? in[ip++] & 0xff : 0; + int i2 = ip < iLen ? in[ip++] & 0xff : 0; + int o0 = i0 >>> 2; + int o1 = ((i0 & 3) << 4) | (i1 >>> 4); + int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); + int o3 = i2 & 0x3F; + out[op++] = map1[o0]; + out[op++] = map1[o1]; + out[op] = op < oDataLen ? map1[o2] : '='; + op++; + out[op] = op < oDataLen ? map1[o3] : '='; + op++; + } + return new String(out); + } + + public static byte[] decode64(String input) { + char[] in = input.toCharArray(); + int iLen = in.length; + if (iLen % 4 != 0) + throw new IllegalArgumentException("Length of Base64 encoded input string is not a multiple of 4."); + while (iLen > 0 && in[iLen - 1] == '=') + iLen--; + int oLen = (iLen * 3) / 4; + byte[] out = new byte[oLen]; + int ip = 0; + int op = 0; + while (ip < iLen) { + int i0 = in[ip++]; + int i1 = in[ip++]; + int i2 = ip < iLen ? in[ip++] : 'A'; + int i3 = ip < iLen ? in[ip++] : 'A'; + if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) + throw new IllegalArgumentException("Illegal character in Base64 encoded data."); + int b0 = map2[i0]; + int b1 = map2[i1]; + int b2 = map2[i2]; + int b3 = map2[i3]; + if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) + throw new IllegalArgumentException("Illegal character in Base64 encoded data."); + int o0 = (b0 << 2) | (b1 >>> 4); + int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2); + int o2 = ((b2 & 3) << 6) | b3; + out[op++] = (byte) o0; + if (op < oLen) + out[op++] = (byte) o1; + if (op < oLen) + out[op++] = (byte) o2; + } + return out; + } +}
Log in to post a comment.
I've created a modification to allow XML to be passed in instead of read from the filesystem
here is the patch:
### Eclipse Workspace Patch 1.0
#P hypergraph
Index: source/hypergraph/graphApi/io/SAXReader.java
===================================================================
RCS file: /cvsroot/hypergraph/hypergraph/source/hypergraph/graphApi/io/SAXReader.java,v
retrieving revision 1.2
diff -u -r1.2 SAXReader.java
--- source/hypergraph/graphApi/io/SAXReader.java 23 Oct 2005 17:20:12 -0000 1.2
+++ source/hypergraph/graphApi/io/SAXReader.java 4 Dec 2008 21:49:44 -0000
@@ -21,6 +21,9 @@
package hypergraph.graphApi.io;
+import hypergraph.graphApi.Graph;
+import hypergraph.graphApi.GraphSystem;
+
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
@@ -29,13 +32,13 @@
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
+import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
-import hypergraph.graphApi.Graph;
-import hypergraph.graphApi.GraphSystem;
-
/**
* @author Jens Kanschik
*
@@ -55,6 +58,12 @@
inputSource = new InputSource(filename);
createLexicalHandler();
}
+
+ public SAXReader(GraphSystem graphSystem, InputSource content) throws FileNotFoundException, IOException{
+ this.graphSystem = graphSystem;
+ inputSource = content;
+ createLexicalHandler();
+ }
public SAXReader(GraphSystem graphSystem, URL url) throws IOException {
this.graphSystem = graphSystem;
inputSource = new InputSource(url.openStream());
@@ -83,12 +92,29 @@
return graph;
}
public Graph parse() throws SAXException, IOException, ParserConfigurationException {
- SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+ return parse(null);
+ }
+ public Graph parse(final InputSource dtd) throws ParserConfigurationException, SAXException,
+ SAXNotRecognizedException, SAXNotSupportedException, IOException {
+ SAXParserFactory parserFactory = SAXParserFactory.newInstance();
SAXParser parser = parserFactory.newSAXParser();
reader = parser.getXMLReader();
- lexicalHandler.setSAXReader(this);
+ if (dtd != null) {
+ reader.setEntityResolver(new EntityResolver() {
+ @Override
+ public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
+ if (systemId.indexOf("GraphXML.dtd") >= 0) {
+ return dtd;
+ } else {
+ return null;
+ }
+ }
+
+ });
+ }
+ lexicalHandler.setSAXReader(this);
reader.setProperty("http://xml.org/sax/properties/lexical-handler", lexicalHandler);
reader.parse(inputSource);
return getGraph();
- }
+ }
}
Index: source/hypergraph/applications/hexplorer/DynamicXmlHExplorerApplet.java
===================================================================
RCS file: source/hypergraph/applications/hexplorer/DynamicXmlHExplorerApplet.java
diff -N source/hypergraph/applications/hexplorer/DynamicXmlHExplorerApplet.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ source/hypergraph/applications/hexplorer/DynamicXmlHExplorerApplet.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2003 Jens Kanschik,
+ * mail : jensKanschik@users.sourceforge.net
+ *
+ * Part of <hypergraph>, an open source project at sourceforge.net
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+package hypergraph.applications.hexplorer;
+
+
+import hypergraph.graphApi.Graph;
+import hypergraph.graphApi.GraphSystem;
+import hypergraph.graphApi.GraphSystemFactory;
+import hypergraph.graphApi.Node;
+import hypergraph.graphApi.algorithms.GraphUtilities;
+import hypergraph.graphApi.io.GraphWriter;
+import hypergraph.graphApi.io.GraphXMLWriter;
+import hypergraph.graphApi.io.SAXReader;
+import hypergraph.visualnet.ArrowLineRenderer;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.URL;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import javax.swing.JApplet;
+import javax.swing.JOptionPane;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * @author Jens Kanschik
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class DynamicXmlHExplorerApplet extends JApplet {
+ private static byte[] dtdbytes;
+ private static final String zipDtd = "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";
+ private static byte[] getDtdBytes() throws IOException {
+ return dtdbytes == null ? dtdbytes = StringZip.unzipBytes(zipDtd) :dtdbytes;
+ }
+
+ /** Stores the graph that the applet shows. */
+ private GraphPanel graphPanel;
+
+ public GraphPanel getGraphPanel() {
+ return graphPanel;
+ }
+ /**@inheritDoc */
+ public void init() {
+ GraphSystem graphSystem = null;
+ try {
+ graphSystem = GraphSystemFactory.createGraphSystem("hypergraph.graph.GraphSystemImpl", null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(8);
+ }
+ Graph graph = null;
+ try {
+ InputSource source = createInput(StringZip
+ .unzipBytes(getParameter("zipcontent")));
+ SAXReader reader = new SAXReader(graphSystem, source);
+ ContentHandlerFactory ch = new ContentHandlerFactory();
+ ch.setBaseUrl(getCodeBase());
+ reader.setContentHandlerFactory(ch);
+ graph = reader.parse(createInput(getDtdBytes()));
+ } catch (SAXException saxe) {
+ JOptionPane.showMessageDialog(null,
+ "Error while parsing dynamic xml. \n" +
+ "Exception : " + saxe + ". \n" +
+ "Start applet with default graph", "Parsing error", JOptionPane.ERROR_MESSAGE);
+ System.out.println("Exception : " + saxe);
+ saxe.getException().printStackTrace();
+ saxe.printStackTrace(System.out);
+ } catch (Exception e) {
+ JOptionPane.showMessageDialog(null,
+ "General error while reading dynamic xml. \n" +
+ "Exception : " + e + ". \n" +
+ "Start applet with default graph", "General error", JOptionPane.ERROR_MESSAGE);
+ System.out.println("Exception : " + e);
+ e.printStackTrace(System.out);
+ }
+
+ if (graph == null) {
+ graph = GraphUtilities.createTree(graphSystem, 2, 3);
+ }
+
+ graphPanel = new GraphPanel(graph, this);
+ String file = getParameter("properties");
+ URL url = null;
+ if (file != null)
+ try {
+ url = new URL(getCodeBase(), file);
+ graphPanel.loadProperties(url.openStream());
+ } catch (FileNotFoundException fnfe) {
+ JOptionPane.showMessageDialog(null,
+ "Could not find propertyfile " + url.getFile() + ". \n" +
+ "Start applet with default properties", "File not found", JOptionPane.ERROR_MESSAGE);
+ } catch (Exception e) {
+ JOptionPane.showMessageDialog(null,
+ "General error while reading file " + url.getFile() + ". \n" +
+ "Exception : " + e + ". \n" +
+ "Start applet with default properties", "General error", JOptionPane.ERROR_MESSAGE);
+ System.out.println("Exception : " + e);
+ e.printStackTrace(System.out);
+ }
+
+ String center = getParameter("center");
+ if (center != null) {
+ Node n = (Node) graph.getElement(center);
+ if (n != null)
+ graphPanel.centerNode(n);
+ }
+ graphPanel.setLineRenderer(new ArrowLineRenderer());
+
+ getContentPane().add(graphPanel);
+ }
+
+ public String getGraphXML() {
+ try {
+ OutputStream os = new ByteArrayOutputStream();
+ GraphWriter graphWriter = new GraphXMLWriter(new OutputStreamWriter(os));
+ graphWriter.write(getGraphPanel().getGraph());
+ return os.toString();
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ return ioe.toString();
+ }
+ }
+
+ private InputSource createInput(byte[] unzipBytes) {
+ return new InputSource(new ByteArrayInputStream(unzipBytes));
+ }
+}
+
+class StringZip {
+ // map 6-bit nibbles into base 64 characters
+ private static char[] map1 = new char[64];
+ static {
+ int i = 0;
+ for (char c = 'A'; c <= 'Z'; c++)
+ map1[i++] = c;
+ for (char c = 'a'; c <= 'z'; c++)
+ map1[i++] = c;
+ for (char c = '0'; c <= '9'; c++)
+ map1[i++] = c;
+ map1[i++] = '+';
+ map1[i++] = '/';
+ }
+
+ // Mapping table from Base64 characters to 6-bit nibbles.
+ private static byte[] map2 = new byte[128];
+ static {
+ for (int i = 0; i < map2.length; i++)
+ map2[i] = -1;
+ for (int i = 0; i < 64; i++)
+ map2[map1[i]] = (byte) i;
+ }
+
+ public static String zip(String input) throws IOException {
+ return encode64(zip(input.getBytes()));
+ }
+
+ public static String unzip(String input) throws IOException {
+ return new String(unzipBytes(input));
+ }
+
+ public static byte[] unzipBytes(String input) throws IOException {
+ return unzip(decode64(input));
+ }
+
+ private static byte[] unzip(byte[] zipped) throws IOException {
+ // TODO Auto-generated method stub
+ InputStream input = new GZIPInputStream(new ByteArrayInputStream(zipped));
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ copy(input, output);
+ input.close();
+ output.close();
+ return output.toByteArray();
+ }
+
+ private static byte[] zip(byte[] unzipped) throws IOException {
+ InputStream input = new ByteArrayInputStream(unzipped);
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ GZIPOutputStream zipout = new GZIPOutputStream(output);
+ copy(input, zipout);
+ input.close();
+ zipout.finish();
+ zipout.close();
+ return output.toByteArray();
+ }
+
+ private static void copy(InputStream input, OutputStream output) throws IOException {
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = input.read(buf)) > 0) {
+ output.write(buf, 0, len);
+ }
+ output.flush();
+ }
+
+ public static String encode64(byte[] in) {
+ int iLen = in.length;
+ int oDataLen = (iLen * 4 + 2) / 3; // output length without padding
+ int oLen = ((iLen + 2) / 3) * 4; // output length including padding
+ char[] out = new char[oLen];
+ int ip = 0;
+ int op = 0;
+ while (ip < iLen) {
+ int i0 = in[ip++] & 0xff;
+ int i1 = ip < iLen ? in[ip++] & 0xff : 0;
+ int i2 = ip < iLen ? in[ip++] & 0xff : 0;
+ int o0 = i0 >>> 2;
+ int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
+ int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
+ int o3 = i2 & 0x3F;
+ out[op++] = map1[o0];
+ out[op++] = map1[o1];
+ out[op] = op < oDataLen ? map1[o2] : '=';
+ op++;
+ out[op] = op < oDataLen ? map1[o3] : '=';
+ op++;
+ }
+ return new String(out);
+ }
+
+ public static byte[] decode64(String input) {
+ char[] in = input.toCharArray();
+ int iLen = in.length;
+ if (iLen % 4 != 0)
+ throw new IllegalArgumentException("Length of Base64 encoded input string is not a multiple of 4.");
+ while (iLen > 0 && in[iLen - 1] == '=')
+ iLen--;
+ int oLen = (iLen * 3) / 4;
+ byte[] out = new byte[oLen];
+ int ip = 0;
+ int op = 0;
+ while (ip < iLen) {
+ int i0 = in[ip++];
+ int i1 = in[ip++];
+ int i2 = ip < iLen ? in[ip++] : 'A';
+ int i3 = ip < iLen ? in[ip++] : 'A';
+ if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
+ throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
+ int b0 = map2[i0];
+ int b1 = map2[i1];
+ int b2 = map2[i2];
+ int b3 = map2[i3];
+ if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
+ throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
+ int o0 = (b0 << 2) | (b1 >>> 4);
+ int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
+ int o2 = ((b2 & 3) << 6) | b3;
+ out[op++] = (byte) o0;
+ if (op < oLen)
+ out[op++] = (byte) o1;
+ if (op < oLen)
+ out[op++] = (byte) o2;
+ }
+ return out;
+ }
+}