librepdf 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/History.md +8 -0
- data/LICENSE +22 -0
- data/README.md +99 -0
- data/Rakefile +52 -0
- data/java/lib/LibreOffice-LICENSE +8817 -0
- data/java/lib/juh.jar +0 -0
- data/java/lib/jurt.jar +0 -0
- data/java/lib/ridl.jar +0 -0
- data/java/lib/unoil.jar +0 -0
- data/java/src/librepdf/Connection.java +231 -0
- data/java/src/librepdf/Utils.java +29 -0
- data/java/src/librepdf/document/Calc.java +25 -0
- data/java/src/librepdf/document/Chart.java +25 -0
- data/java/src/librepdf/document/Document.java +124 -0
- data/java/src/librepdf/document/Draw.java +25 -0
- data/java/src/librepdf/document/Factory.java +59 -0
- data/java/src/librepdf/document/Global.java +25 -0
- data/java/src/librepdf/document/Impress.java +25 -0
- data/java/src/librepdf/document/Math.java +25 -0
- data/java/src/librepdf/document/Web.java +25 -0
- data/java/src/librepdf/document/Writer.java +25 -0
- data/lib/librepdf.rb +29 -0
- data/lib/librepdf/version.rb +3 -0
- data/librepdf.gemspec +20 -0
- data/spec/data/test.odt +0 -0
- data/spec/librepdf_spec.rb +92 -0
- data/spec/spec_helper.rb +7 -0
- metadata +100 -0
data/java/lib/juh.jar
ADDED
Binary file
|
data/java/lib/jurt.jar
ADDED
Binary file
|
data/java/lib/ridl.jar
ADDED
Binary file
|
data/java/lib/unoil.jar
ADDED
Binary file
|
@@ -0,0 +1,231 @@
|
|
1
|
+
|
2
|
+
package librepdf;
|
3
|
+
|
4
|
+
import librepdf.document.Factory;
|
5
|
+
import librepdf.document.Document;
|
6
|
+
|
7
|
+
import java.io.Closeable;
|
8
|
+
import java.io.IOException;
|
9
|
+
import java.util.Map;
|
10
|
+
import java.util.HashMap;
|
11
|
+
import java.net.ConnectException;
|
12
|
+
import org.jruby.*;
|
13
|
+
import org.jruby.runtime.ThreadContext;
|
14
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
15
|
+
import org.jruby.javasupport.JavaEmbedUtils;
|
16
|
+
|
17
|
+
import com.sun.star.beans.XPropertySet;
|
18
|
+
import com.sun.star.beans.PropertyValue;
|
19
|
+
import com.sun.star.bridge.XBridge;
|
20
|
+
import com.sun.star.bridge.XBridgeFactory;
|
21
|
+
import com.sun.star.comp.helper.Bootstrap;
|
22
|
+
import com.sun.star.connection.NoConnectException;
|
23
|
+
import com.sun.star.connection.XConnection;
|
24
|
+
import com.sun.star.connection.XConnector;
|
25
|
+
import com.sun.star.frame.XComponentLoader;
|
26
|
+
import com.sun.star.frame.XStorable;
|
27
|
+
import com.sun.star.lang.EventObject;
|
28
|
+
import com.sun.star.lang.XComponent;
|
29
|
+
import com.sun.star.lang.XEventListener;
|
30
|
+
import com.sun.star.lang.XMultiComponentFactory;
|
31
|
+
import com.sun.star.task.ErrorCodeIOException;
|
32
|
+
import com.sun.star.uno.UnoRuntime;
|
33
|
+
import com.sun.star.uno.XComponentContext;
|
34
|
+
|
35
|
+
public final class Connection implements Closeable, Finalizable
|
36
|
+
{
|
37
|
+
public static String DEFAULT_HOST = "127.0.0.1";
|
38
|
+
public static int DEFAULT_PORT = 8100;
|
39
|
+
|
40
|
+
private final Ruby runtime;
|
41
|
+
private final String host;
|
42
|
+
private final int port;
|
43
|
+
|
44
|
+
private boolean closed = false;
|
45
|
+
|
46
|
+
private XComponent bridgeComponent;
|
47
|
+
private XComponentContext componentContext;
|
48
|
+
private XMultiComponentFactory serviceManager;
|
49
|
+
|
50
|
+
public Connection() throws ConnectException {
|
51
|
+
this(new HashMap<String, Object>(), null);
|
52
|
+
}
|
53
|
+
|
54
|
+
public Connection(RubyProc proc) throws ConnectException {
|
55
|
+
this(new HashMap<String, Object>(), proc);
|
56
|
+
}
|
57
|
+
|
58
|
+
public Connection(Map<String, Object> options) throws ConnectException {
|
59
|
+
this(options, null);
|
60
|
+
}
|
61
|
+
|
62
|
+
public Connection(Map<String, Object> options, RubyProc proc) throws ConnectException {
|
63
|
+
this.runtime = Ruby.getGlobalRuntime();
|
64
|
+
this.runtime.addInternalFinalizer(this);
|
65
|
+
|
66
|
+
if (options.containsKey("host")) {
|
67
|
+
this.host = options.get("host").toString();
|
68
|
+
} else {
|
69
|
+
this.host = DEFAULT_HOST;
|
70
|
+
}
|
71
|
+
if (options.containsKey("port")) {
|
72
|
+
final Object p = options.get("port");
|
73
|
+
if (!(p instanceof Long)) {
|
74
|
+
throw new IllegalArgumentException("The port required the number between 0-65535.");
|
75
|
+
}
|
76
|
+
|
77
|
+
final Long l = (Long)p;
|
78
|
+
if (!(0 < l && l < 65536)) {
|
79
|
+
throw new IllegalArgumentException("The port required the number between 0-65535.");
|
80
|
+
}
|
81
|
+
this.port = l.intValue();
|
82
|
+
} else {
|
83
|
+
this.port = DEFAULT_PORT;
|
84
|
+
}
|
85
|
+
|
86
|
+
this.open();
|
87
|
+
if (proc != null) {
|
88
|
+
try {
|
89
|
+
final ThreadContext context = this.runtime.getCurrentContext();
|
90
|
+
final IRubyObject[] args = { JavaEmbedUtils.javaToRuby(this.runtime, this) };
|
91
|
+
proc.call(context, args);
|
92
|
+
} finally {
|
93
|
+
try {
|
94
|
+
this.close();
|
95
|
+
} catch (Exception e) {
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
@Override
|
102
|
+
public void finalize() throws Throwable {
|
103
|
+
try {
|
104
|
+
this.close();
|
105
|
+
} catch(IOException e) {}
|
106
|
+
}
|
107
|
+
|
108
|
+
@Override
|
109
|
+
public synchronized void close() throws IOException {
|
110
|
+
if (!this.closed) {
|
111
|
+
this.bridgeComponent.dispose();
|
112
|
+
this.runtime.removeInternalFinalizer(this);
|
113
|
+
this.closed = true;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
@Override
|
118
|
+
public String toString() {
|
119
|
+
return "#<Librepdf::Connection host=" + this.host + ",port=" + this.port + ">";
|
120
|
+
}
|
121
|
+
|
122
|
+
public boolean isClosed() {
|
123
|
+
return this.closed;
|
124
|
+
}
|
125
|
+
|
126
|
+
public String inspect() {
|
127
|
+
return this.toString();
|
128
|
+
}
|
129
|
+
|
130
|
+
private synchronized void open() throws ConnectException {
|
131
|
+
final String connectionString = "socket,host=" + this.host + ",port=" + this.port + ",tcpNoDelay=1";
|
132
|
+
|
133
|
+
try {
|
134
|
+
final XComponentContext localContext = Bootstrap.createInitialComponentContext(null);
|
135
|
+
final XMultiComponentFactory localServiceManager = localContext.getServiceManager();
|
136
|
+
final XConnector connector = (XConnector) UnoRuntime.queryInterface(XConnector.class, localServiceManager
|
137
|
+
.createInstanceWithContext("com.sun.star.connection.Connector", localContext));
|
138
|
+
final XConnection connection = connector.connect(connectionString);
|
139
|
+
final XBridgeFactory bridgeFactory = (XBridgeFactory) UnoRuntime.queryInterface(XBridgeFactory.class,
|
140
|
+
localServiceManager.createInstanceWithContext("com.sun.star.bridge.BridgeFactory", localContext));
|
141
|
+
final XBridge bridge = bridgeFactory.createBridge("", "urp", connection, null);
|
142
|
+
|
143
|
+
this.bridgeComponent = (XComponent) UnoRuntime.queryInterface(XComponent.class, bridge);
|
144
|
+
this.serviceManager = (XMultiComponentFactory) UnoRuntime.queryInterface(XMultiComponentFactory.class,
|
145
|
+
bridge.getInstance("StarOffice.ServiceManager"));
|
146
|
+
|
147
|
+
final XPropertySet properties = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class,
|
148
|
+
this.serviceManager);
|
149
|
+
this.componentContext = (XComponentContext) UnoRuntime.queryInterface(XComponentContext.class, properties
|
150
|
+
.getPropertyValue("DefaultContext"));
|
151
|
+
|
152
|
+
} catch (Exception e) {
|
153
|
+
throw new ConnectException("connection failed: " + connectionString + ": " + e.getMessage());
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
public Document load(String inputUrl) {
|
158
|
+
return this.load(inputUrl, new HashMap<String, Object>());
|
159
|
+
}
|
160
|
+
|
161
|
+
public Document load(String inputUrl, Map<String, Object> options) {
|
162
|
+
if (inputUrl == null) {
|
163
|
+
throw new IllegalArgumentException("Null connot be set for inputUrl.");
|
164
|
+
}
|
165
|
+
if (this.closed) {
|
166
|
+
throw new IllegalArgumentException("The connection has not established it.");
|
167
|
+
}
|
168
|
+
|
169
|
+
options.put("Hidden", true);
|
170
|
+
options.put("ReadOnly", true);
|
171
|
+
final PropertyValue[] inputProperties = Utils.toPropertyValues(options);
|
172
|
+
|
173
|
+
final XComponent document = this.loadInternal(inputUrl, inputProperties);
|
174
|
+
|
175
|
+
return Factory.factory(this, this.runtime, document);
|
176
|
+
}
|
177
|
+
|
178
|
+
public Document load(String inputUrl, RubyProc proc) {
|
179
|
+
return this.load(inputUrl, new HashMap<String, Object>(), proc);
|
180
|
+
}
|
181
|
+
|
182
|
+
public Document load(String inputUrl, Map<String, Object> options, RubyProc proc) {
|
183
|
+
if (inputUrl == null) {
|
184
|
+
throw new IllegalArgumentException("Null connot be set for inputUrl.");
|
185
|
+
}
|
186
|
+
if (this.closed) {
|
187
|
+
throw new IllegalArgumentException("The connection has not established it.");
|
188
|
+
}
|
189
|
+
|
190
|
+
options.put("Hidden", true);
|
191
|
+
options.put("ReadOnly", true);
|
192
|
+
final PropertyValue[] inputProperties = Utils.toPropertyValues(options);
|
193
|
+
|
194
|
+
final XComponent document = this.loadInternal(inputUrl, inputProperties);
|
195
|
+
|
196
|
+
return Factory.factory(this, this.runtime, document, proc);
|
197
|
+
}
|
198
|
+
|
199
|
+
private XComponentLoader getDesktop() {
|
200
|
+
return (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class,
|
201
|
+
this.getService("com.sun.star.frame.Desktop"));
|
202
|
+
}
|
203
|
+
|
204
|
+
private Object getService(String className) {
|
205
|
+
if (className == null) {
|
206
|
+
throw new IllegalArgumentException("Null connot be set for className.");
|
207
|
+
}
|
208
|
+
|
209
|
+
try {
|
210
|
+
return this.serviceManager.createInstanceWithContext(className, this.componentContext);
|
211
|
+
|
212
|
+
} catch (Exception e) {
|
213
|
+
throw new RuntimeException("could not obtain service: " + className, e);
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|
217
|
+
private XComponent loadInternal(String inputUrl, PropertyValue[] properties) {
|
218
|
+
final XComponentLoader desktop = this.getDesktop();
|
219
|
+
try {
|
220
|
+
return desktop.loadComponentFromURL(inputUrl, "_blank", 0, properties);
|
221
|
+
|
222
|
+
} catch (ErrorCodeIOException e) {
|
223
|
+
throw new RuntimeException("could not load input document. " + e.ErrCode, e);
|
224
|
+
|
225
|
+
} catch (Exception e) {
|
226
|
+
throw new RuntimeException("could not load input document.", e);
|
227
|
+
|
228
|
+
}
|
229
|
+
}
|
230
|
+
}
|
231
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
package librepdf;
|
3
|
+
|
4
|
+
import java.util.Map;
|
5
|
+
import java.util.Iterator;
|
6
|
+
import com.sun.star.beans.PropertyValue;
|
7
|
+
|
8
|
+
public final class Utils
|
9
|
+
{
|
10
|
+
public static PropertyValue[] toPropertyValues(Map properties) {
|
11
|
+
final PropertyValue[] ret = new PropertyValue[properties.size()];
|
12
|
+
int i = 0;
|
13
|
+
for (Iterator it = properties.entrySet().iterator(); it.hasNext();) {
|
14
|
+
Map.Entry entry = (Map.Entry)it.next();
|
15
|
+
String key = entry.getKey().toString();
|
16
|
+
Object val = entry.getValue();
|
17
|
+
|
18
|
+
ret[i] = new PropertyValue();
|
19
|
+
ret[i].Name = key;
|
20
|
+
ret[i].Value = (val instanceof Map) ? Utils.toPropertyValues((Map)val) : val;
|
21
|
+
|
22
|
+
i++;
|
23
|
+
}
|
24
|
+
return ret;
|
25
|
+
}
|
26
|
+
|
27
|
+
private Utils() {}
|
28
|
+
}
|
29
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
package librepdf.document;
|
3
|
+
|
4
|
+
import librepdf.Connection;
|
5
|
+
import java.util.Map;
|
6
|
+
import org.jruby.Ruby;
|
7
|
+
import org.jruby.RubyProc;
|
8
|
+
import com.sun.star.lang.XComponent;
|
9
|
+
|
10
|
+
class Calc extends Document
|
11
|
+
{
|
12
|
+
Calc(Connection connection, Ruby runtime, XComponent document) {
|
13
|
+
super(connection, runtime, document);
|
14
|
+
}
|
15
|
+
|
16
|
+
Calc(Connection connection, Ruby runtime, XComponent document, RubyProc proc) {
|
17
|
+
super(connection, runtime, document, proc);
|
18
|
+
}
|
19
|
+
|
20
|
+
@Override
|
21
|
+
protected void setDefaultOptions(Map<String, Object> options) {
|
22
|
+
options.put("FilterName", "calc_pdf_Export");
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
package librepdf.document;
|
3
|
+
|
4
|
+
import librepdf.Connection;
|
5
|
+
import java.util.Map;
|
6
|
+
import org.jruby.Ruby;
|
7
|
+
import org.jruby.RubyProc;
|
8
|
+
import com.sun.star.lang.XComponent;
|
9
|
+
|
10
|
+
class Chart extends Document
|
11
|
+
{
|
12
|
+
Chart(Connection connection, Ruby runtime, XComponent document) {
|
13
|
+
super(connection, runtime, document);
|
14
|
+
}
|
15
|
+
|
16
|
+
Chart(Connection connection, Ruby runtime, XComponent document, RubyProc proc) {
|
17
|
+
super(connection, runtime, document, proc);
|
18
|
+
}
|
19
|
+
|
20
|
+
@Override
|
21
|
+
protected void setDefaultOptions(Map<String, Object> options) {
|
22
|
+
options.put("FilterName", "chart_pdf_Export");
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
@@ -0,0 +1,124 @@
|
|
1
|
+
|
2
|
+
package librepdf.document;
|
3
|
+
|
4
|
+
import librepdf.Connection;
|
5
|
+
import librepdf.Utils;
|
6
|
+
|
7
|
+
import java.util.Map;
|
8
|
+
import java.util.HashMap;
|
9
|
+
import java.io.Closeable;
|
10
|
+
import java.io.IOException;
|
11
|
+
import org.jruby.*;
|
12
|
+
import org.jruby.runtime.ThreadContext;
|
13
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
14
|
+
import org.jruby.javasupport.JavaEmbedUtils;
|
15
|
+
|
16
|
+
import com.sun.star.beans.PropertyValue;
|
17
|
+
import com.sun.star.frame.XStorable;
|
18
|
+
import com.sun.star.util.XCloseable;
|
19
|
+
import com.sun.star.util.CloseVetoException;
|
20
|
+
import com.sun.star.task.ErrorCodeIOException;
|
21
|
+
import com.sun.star.lang.XComponent;
|
22
|
+
import com.sun.star.lang.XServiceInfo;
|
23
|
+
import com.sun.star.uno.UnoRuntime;
|
24
|
+
|
25
|
+
public abstract class Document implements Closeable, Finalizable
|
26
|
+
{
|
27
|
+
private final Connection connection;
|
28
|
+
private final Ruby runtime;
|
29
|
+
private final XComponent document;
|
30
|
+
|
31
|
+
private boolean closed = false;
|
32
|
+
|
33
|
+
Document(Connection connection, Ruby runtime, XComponent document) {
|
34
|
+
this.connection = connection;
|
35
|
+
this.runtime = runtime;
|
36
|
+
this.document = document;
|
37
|
+
this.runtime.addInternalFinalizer(this);
|
38
|
+
}
|
39
|
+
|
40
|
+
Document(Connection connection, Ruby runtime, XComponent document, RubyProc proc) {
|
41
|
+
this(connection, runtime, document);
|
42
|
+
|
43
|
+
final ThreadContext context = this.runtime.getCurrentContext();
|
44
|
+
final IRubyObject[] args = { JavaEmbedUtils.javaToRuby(this.runtime, this) };
|
45
|
+
|
46
|
+
try {
|
47
|
+
proc.call(context, args);
|
48
|
+
} finally {
|
49
|
+
try {
|
50
|
+
this.close();
|
51
|
+
} catch (Exception e) {
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
@Override
|
57
|
+
public void finalize() throws Throwable {
|
58
|
+
try {
|
59
|
+
close();
|
60
|
+
} catch (IOException e) {}
|
61
|
+
}
|
62
|
+
|
63
|
+
@Override
|
64
|
+
public void close() throws IOException {
|
65
|
+
if (!this.closed) {
|
66
|
+
final XCloseable closeable = (XCloseable) UnoRuntime.queryInterface(XCloseable.class, document);
|
67
|
+
try {
|
68
|
+
closeable.close(false);
|
69
|
+
} catch (CloseVetoException e) {
|
70
|
+
throw new IOException("chould not close document.", e);
|
71
|
+
}
|
72
|
+
this.runtime.removeInternalFinalizer(this);
|
73
|
+
this.closed = true;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
public void convertPdf(String outputUrl) {
|
78
|
+
this.convertPdf(outputUrl, new HashMap<String, Object>());
|
79
|
+
}
|
80
|
+
|
81
|
+
public void convertPdf(String outputUrl, Map<String, Object> options) {
|
82
|
+
if (outputUrl == null) {
|
83
|
+
throw new IllegalArgumentException("Null connot be set for outputUrl.");
|
84
|
+
}
|
85
|
+
if (this.connection.isClosed()) {
|
86
|
+
throw new IllegalArgumentException("The connection has not established it.");
|
87
|
+
}
|
88
|
+
|
89
|
+
final XStorable storable = (XStorable) UnoRuntime.queryInterface(XStorable.class, document);
|
90
|
+
|
91
|
+
if (!options.containsKey("FilterData")) options.put("FilterData", new HashMap<String, Object>());
|
92
|
+
this.setDefaultOptions(options);
|
93
|
+
final PropertyValue[] outputProperties = Utils.toPropertyValues(options);
|
94
|
+
|
95
|
+
try {
|
96
|
+
storable.storeToURL(outputUrl, outputProperties);
|
97
|
+
|
98
|
+
} catch (ErrorCodeIOException e) {
|
99
|
+
throw new RuntimeException("could not save output document. " + e.ErrCode, e);
|
100
|
+
|
101
|
+
} catch (Exception e) {
|
102
|
+
throw new RuntimeException("could not save output document", e);
|
103
|
+
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
@Override
|
108
|
+
public String toString() {
|
109
|
+
return "#<Librepdf::Document::" + this.getClass().getSimpleName() + ">";
|
110
|
+
}
|
111
|
+
|
112
|
+
public boolean isClosed() {
|
113
|
+
return this.closed;
|
114
|
+
}
|
115
|
+
|
116
|
+
public String inspect() {
|
117
|
+
return this.toString();
|
118
|
+
}
|
119
|
+
|
120
|
+
protected void setDefaultOptions(Map<String, Object> options) {
|
121
|
+
// do nothing.
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
package librepdf.document;
|
3
|
+
|
4
|
+
import librepdf.Connection;
|
5
|
+
import java.util.Map;
|
6
|
+
import org.jruby.Ruby;
|
7
|
+
import org.jruby.RubyProc;
|
8
|
+
import com.sun.star.lang.XComponent;
|
9
|
+
|
10
|
+
class Draw extends Document
|
11
|
+
{
|
12
|
+
Draw(Connection connection, Ruby runtime, XComponent document) {
|
13
|
+
super(connection, runtime, document);
|
14
|
+
}
|
15
|
+
|
16
|
+
Draw(Connection connection, Ruby runtime, XComponent document, RubyProc proc) {
|
17
|
+
super(connection, runtime, document, proc);
|
18
|
+
}
|
19
|
+
|
20
|
+
@Override
|
21
|
+
protected void setDefaultOptions(Map<String, Object> options) {
|
22
|
+
options.put("FilterName", "draw_pdf_Export");
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|