LibreOffice Module unotest (master) 1
OfficeConnection.java
Go to the documentation of this file.
1/*
2 * This file is part of the LibreOffice project.
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 *
8 * This file incorporates work covered by the following license notice:
9 *
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
17 */
18
19package org.openoffice.test;
20
21import com.sun.star.bridge.UnoUrlResolver;
22import com.sun.star.bridge.XUnoUrlResolver;
23import com.sun.star.comp.helper.Bootstrap;
24import com.sun.star.connection.NoConnectException;
25import com.sun.star.frame.XDesktop;
26import com.sun.star.lang.DisposedException;
27import com.sun.star.lang.XMultiComponentFactory;
28import com.sun.star.uno.UnoRuntime;
29import com.sun.star.uno.XComponentContext;
30import java.io.File;
31import java.io.IOException;
32import java.io.InputStream;
33import java.io.PrintStream;
34import java.util.Map;
35import java.util.UUID;
36import static org.junit.Assert.*;
37
45public final class OfficeConnection {
48 public void setUp() throws Exception {
49 String sofficeArg = Argument.get("soffice");
50 if (sofficeArg.startsWith("path:")) {
51 description = "pipe,name=oootest" + UUID.randomUUID();
52 ProcessBuilder pb = new ProcessBuilder(
53 sofficeArg.substring("path:".length()), "--quickstart=no",
54 "--norestore", "--nologo", "--headless",
55 "--accept=" + description + ";urp",
56 "-env:UserInstallation=" + Argument.get("user"),
57 "-env:UNO_JAVA_JFW_ENV_JREHOME=true");
58 String workdirArg = Argument.get("workdir");
59 if (workdirArg != null) {
60 pb.directory(new File(workdirArg));
61 }
62 String envArg = Argument.get("env");
63 if (envArg != null) {
64 Map<String, String> env = pb.environment();
65 int i = envArg.indexOf('=');
66 if (i == -1) {
67 env.remove(envArg);
68 } else {
69 env.put(envArg.substring(0, i), envArg.substring(i + 1));
70 }
71 }
72 process = pb.start();
73 outForward = new Forward(process.getInputStream(), System.out);
74 outForward.start();
75 errForward = new Forward(process.getErrorStream(), System.err);
76 errForward.start();
77 } else if (sofficeArg.startsWith("connect:")) {
78 description = sofficeArg.substring("connect:".length());
79 } else {
80 fail(
81 "\"soffice\" argument \"" + sofficeArg +
82 " starts with neither \"path:\" nor \"connect:\"");
83 }
84 XUnoUrlResolver resolver = UnoUrlResolver.create(
85 Bootstrap.createInitialComponentContext(null));
86 for (;;) {
87 try {
88 context = UnoRuntime.queryInterface(
89 XComponentContext.class,
90 resolver.resolve(
91 "uno:" + description +
92 ";urp;StarOffice.ComponentContext"));
93 break;
94 } catch (NoConnectException e) {}
95 if (process != null) {
96 assertNull(waitForProcess(process, 1000)); // 1 sec
97 }
98 }
99 }
100
103 public void tearDown()
104 throws InterruptedException, com.sun.star.uno.Exception
105 {
106 boolean cleanTermination = false;
107 int code = 0;
108 try {
109 if (process != null) {
110 if (context != null) {
111 XDesktop desktop = null;
112 try {
113 XMultiComponentFactory factory =
114 context.getServiceManager();
115 assertNotNull(factory);
116 desktop = UnoRuntime.queryInterface(XDesktop.class,
117 factory.createInstanceWithContext(
118 "com.sun.star.frame.Desktop", context));
119 } catch (DisposedException e) {
120 // it can happen that the Java bridge was disposed
121 // already, we want to ensure soffice.bin is killed
122 process.destroy();
123 }
124 context = null;
125 if (desktop != null) {
126 try {
127 boolean desktopTerminated = desktop.terminate();
128 if (!desktopTerminated) {
129 // in case terminate() fails we would wait
130 // forever for the process to die, so kill it
131 process.destroy();
132 }
133 assertTrue(desktopTerminated);
134 } catch (DisposedException e) {}
135 // it appears that DisposedExceptions can already happen
136 // while receiving the response of the terminate call
137 }
138 desktop = null;
139 } else {
140 process.destroy();
141 }
142 }
143 if (process != null) {
144 code = process.waitFor();
145 }
146 boolean outTerminated = outForward == null
148 boolean errTerminated = errForward == null
150 assertEquals(0, code);
151 cleanTermination = true;
152 assertTrue(outTerminated);
153 assertTrue(errTerminated);
154 } finally {
155 if (!cleanTermination) {
156 try {
157 String sofficeArg = Argument.get("soffice");
158 String workdir = Argument.get("workdir");
159 String postprocesscommand = Argument.get(
160 "postprocesscommand");
161 if (sofficeArg.startsWith("path:") && workdir != null
162 && postprocesscommand != null)
163 {
164 ProcessBuilder pb = new ProcessBuilder(
165 postprocesscommand,
166 sofficeArg.substring("path:".length()) + ".bin",
167 workdir, String.valueOf(code));
168 Process postprocess = pb.start();
169 Forward ppoutForward = new Forward(
170 postprocess.getInputStream(), System.out);
171 ppoutForward.start();
172 Forward pperrForward = new Forward(
173 postprocess.getErrorStream(), System.err);
174 pperrForward.start();
175 code = postprocess.waitFor();
176 if (code != 0) {
178 }
179 }
180 }
181 catch (IOException e) {
182 throw new PostprocessFailedException(e);
183 }
184 }
185 }
186 }
187
190 public XComponentContext getComponentContext() {
191 return context;
192 }
193
194 //TODO: get rid of this hack for legacy qa/unoapi tests
196 return description;
197 }
198
199 private static Integer waitForProcess(Process process, final int millis)
200 throws InterruptedException
201 {
202 final Thread t1 = Thread.currentThread();
203 Thread t2 = new Thread("waitForProcess") {
204 @Override
205 public void run() {
206 util.utils.pause(millis);
207 t1.interrupt();
208 }
209 };
210 boolean old = Thread.interrupted();
211 // clear interrupted status, get old status
212 t2.start();
213 int n = 0;
214 boolean done = false;
215 try {
216 n = process.waitFor();
217 done = true;
218 } catch (InterruptedException e) {}
219 t2.interrupt();
220 try {
221 t2.join();
222 } catch (InterruptedException e) {
223 t2.join();
224 }
225 Thread.interrupted(); // clear interrupted status
226 if (old) {
227 t1.interrupt(); // reset old status
228 }
229 return done ? Integer.valueOf(n) : null;
230 }
231
232 private static final class Forward extends Thread {
233 public Forward(InputStream in, PrintStream out) {
234 super("process output forwarder");
235 this.in = in;
236 this.out = out;
237 }
238
239 @Override
240 public void run() {
241 for (;;) {
242 byte[] buf = new byte[1024];
243 int n;
244 try {
245 n = in.read(buf);
246 } catch (IOException e) {
247 throw new RuntimeException("wrapping", e);
248 }
249 if (n == -1) {
250 break;
251 }
252 out.write(buf, 0, n);
253 }
254 done = true;
255 }
256
257 public boolean terminated() throws InterruptedException {
258 join();
259 return done;
260 }
261
262 private final InputStream in;
263 private final PrintStream out;
264 private boolean done = false;
265 }
266
267 private static final class PostprocessFailedException
268 extends RuntimeException
269 {
270 PostprocessFailedException(int exitCode) {
271 super("postprocessing failed with exit code " + exitCode);
272 }
273
274 PostprocessFailedException(IOException cause) {
275 super("postprocessing failed with IOException " + cause, cause);
276 }
277 }
278
280 private Process process = null;
281 private Forward outForward = null;
282 private Forward errForward = null;
283 private XComponentContext context = null;
284}
285// vim:set et sw=4 sts=4:
static String get(String name)
Definition: Argument.java:22
Forward(InputStream in, PrintStream out)
Start up and shut down an OOo instance.
XComponentContext getComponentContext()
Obtain the component context of the running OOo instance.
void setUp()
Start up an OOo instance.
void tearDown()
Shut down the OOo instance.
static Integer waitForProcess(Process process, final int millis)
sal_Int64 n
const css::uno::Reference< css::xml::crypto::XSecurityEnvironment > & env
def run(arg=None, arg2=-1)
void SC_DLLPUBLIC join(const ScDocument *pDoc, ::std::vector< ScTokenRef > &rTokens, const ScTokenRef &pToken, const ScAddress &rPos)
int i
const rtl::Bootstrap * Bootstrap()
resolver
sal_Unicode code