parent
d2f34333b7
commit
b3a74388fe
@ -1,13 +1,42 @@
|
||||
# ---> Maven
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
nbproject/private/
|
||||
build/
|
||||
nbbuild/
|
||||
dist/
|
||||
nbdist/
|
||||
.nb-gradle/
|
||||
/*.iml
|
||||
|
||||
**/target/
|
||||
.classpath
|
||||
.project
|
||||
**/.settings
|
||||
**/build/
|
||||
**/.externalToolBuilders/
|
||||
*.iml
|
||||
**/.idea/
|
||||
**/disconf
|
||||
**/rpc.properties
|
||||
/producer/tmp
|
||||
/.temfile
|
||||
.temfile
|
||||
convertedFile/
|
||||
jodconverter-web/src/main/cache/
|
||||
jodconverter-web/src/main/file/
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"java.configuration.updateBuildConfiguration": "automatic",
|
||||
"git.ignoreLimitWarning": true
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
FROM centos:centos7.6.1810
|
||||
MAINTAINER chenjh "842761733@qq.com"
|
||||
ADD jodconverter-web/target/kkFileView-*.tar.gz /opt/
|
||||
COPY fonts/* /usr/share/fonts/chienes/
|
||||
RUN yum install -y kde-l10n-Chinese &&\
|
||||
yum install -y glibc-common &&\
|
||||
yum install -y fontconfig &&\
|
||||
yum install -y mkfontscale &&\
|
||||
localedef -c -f UTF-8 -i zh_CN zh_CN.utf8 &&\
|
||||
echo "LANG=zh_CN.UTF-8" > /etc/locale.conf &&\
|
||||
source /etc/locale.conf &&\
|
||||
export LANG=zh_CN.UTF-8 &&\
|
||||
LANG="zh_CN.UTF-8" &&\
|
||||
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&\
|
||||
yum install -y java-1.8.0-openjdk.x86_64 &&\
|
||||
yum install -y wget &&\
|
||||
yum install -y libXext.x86_64 &&\
|
||||
yum groupinstall -y "X Window System" &&\
|
||||
cd /tmp &&\
|
||||
wget https://kkfileview.keking.cn/Apache_OpenOffice_4.1.6_Linux_x86-64_install-rpm_zh-CN.tar.gz -cO openoffice_rpm.tar.gz &&\
|
||||
tar zxf /tmp/openoffice_rpm.tar.gz &&\
|
||||
cd /tmp/zh-CN/RPMS &&\
|
||||
rpm -Uvih *.rpm &&\
|
||||
rpm -Uvih desktop-integration/openoffice4.1.6-redhat-menus-4.1.6-9790.noarch.rpm &&\
|
||||
rm -f /tmp/openoffice_rpm.tar.gz &&\
|
||||
rm -rf /tmp/zh-CN &&\
|
||||
cd /usr/share/fonts/chienes &&\
|
||||
mkfontscale &&\
|
||||
mkfontdir &&\
|
||||
fc-cache -fv
|
||||
ENV LANG zh_CN.UTF-8
|
||||
ENV LC_ALL zh_CN.UTF-8
|
||||
ENV KKFILEVIEW_BIN_FOLDER /opt/kkFileView-2.2.0-SNAPSHOT/bin
|
||||
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider","-Dspring.config.location=/opt/kkFileView-2.2.0-SNAPSHOT/config/application.properties","-jar","/opt/kkFileView-2.2.0-SNAPSHOT/bin/kkFileView-2.2.0-SNAPSHOT.jar"]
|
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed 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.
|
@ -1,3 +1,9 @@
|
||||
# fileview
|
||||
# file-online-preview
|
||||
此项目为文件文档在线预览项目解决方案
|
||||
|
||||
## 构建
|
||||
|
||||
```
|
||||
mvn clean package
|
||||
```
|
||||
|
||||
文档在线预览
|
@ -0,0 +1,160 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>cn.keking</groupId>
|
||||
<artifactId>jodconverter-core</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<repositories>
|
||||
<repository>
|
||||
<!-- required for org.hyperic:sigar -->
|
||||
<id>jboss-public-repository-group</id>
|
||||
<url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openoffice</groupId>
|
||||
<artifactId>juh</artifactId>
|
||||
<version>3.2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openoffice</groupId>
|
||||
<artifactId>ridl</artifactId>
|
||||
<version>3.2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openoffice</groupId>
|
||||
<artifactId>unoil</artifactId>
|
||||
<version>3.2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- for the command line tool -->
|
||||
<groupId>commons-cli</groupId>
|
||||
<artifactId>commons-cli</artifactId>
|
||||
<version>1.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hyperic</groupId>
|
||||
<artifactId>sigar</artifactId>
|
||||
<version>1.6.5.132</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20190722</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<version>6.0.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- 要将源码放上去,需要加入这个插件 -->
|
||||
<plugin>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.1</version>
|
||||
<configuration>
|
||||
<attach>true</attach>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.7.2</version>
|
||||
<configuration>
|
||||
<!-- don't run tests in parallel -->
|
||||
<perCoreThreadCount>false</perCoreThreadCount>
|
||||
<threadCount>1</threadCount>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.3.1</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>org.artofsolving.jodconverter.cli.Convert</mainClass>
|
||||
<addClasspath>true</addClasspath>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.2-beta-5</version>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/dist.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.7</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
<!-- distribute目录 -->
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>repo</id>
|
||||
<name>User Project Releases</name>
|
||||
<url>http://192.168.1.204:8081/nexus/content/repositories/releases</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>repo</id>
|
||||
<name>User Project SNAPSHOTS</name>
|
||||
<url>http://192.168.1.204:8081/nexus/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
</project>
|
@ -0,0 +1,37 @@
|
||||
<assembly>
|
||||
<id>dist</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<outputDirectory>lib</outputDirectory>
|
||||
<excludes>
|
||||
<exclude>org.hyperic:sigar</exclude>
|
||||
</excludes>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<includes>
|
||||
<include>LICENSE.txt</include>
|
||||
<include>README.txt</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>target</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<includes>
|
||||
<include>${project.artifactId}-${project.version}-javadoc.jar</include>
|
||||
<include>${project.artifactId}-${project.version}-sources.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>src/main/resources</directory>
|
||||
<outputDirectory>/conf</outputDirectory>
|
||||
<includes>
|
||||
<include>document-formats.js</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
@ -0,0 +1,125 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter;
|
||||
|
||||
import static org.artofsolving.jodconverter.office.OfficeUtils.SERVICE_DESKTOP;
|
||||
import static org.artofsolving.jodconverter.office.OfficeUtils.cast;
|
||||
import static org.artofsolving.jodconverter.office.OfficeUtils.toUnoProperties;
|
||||
import static org.artofsolving.jodconverter.office.OfficeUtils.toUrl;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
import org.artofsolving.jodconverter.office.OfficeContext;
|
||||
import org.artofsolving.jodconverter.office.OfficeException;
|
||||
import org.artofsolving.jodconverter.office.OfficeTask;
|
||||
|
||||
import com.sun.star.frame.XComponentLoader;
|
||||
import com.sun.star.frame.XStorable;
|
||||
import com.sun.star.io.IOException;
|
||||
import com.sun.star.lang.IllegalArgumentException;
|
||||
import com.sun.star.lang.XComponent;
|
||||
import com.sun.star.task.ErrorCodeIOException;
|
||||
import com.sun.star.util.CloseVetoException;
|
||||
import com.sun.star.util.XCloseable;
|
||||
|
||||
public abstract class AbstractConversionTask implements OfficeTask {
|
||||
|
||||
private final File inputFile;
|
||||
private final File outputFile;
|
||||
|
||||
public AbstractConversionTask(File inputFile, File outputFile) {
|
||||
this.inputFile = inputFile;
|
||||
this.outputFile = outputFile;
|
||||
}
|
||||
|
||||
protected abstract Map<String,?> getLoadProperties(File inputFile);
|
||||
|
||||
protected abstract Map<String,?> getStoreProperties(File outputFile, XComponent document);
|
||||
|
||||
public void execute(OfficeContext context) throws OfficeException {
|
||||
XComponent document = null;
|
||||
try {
|
||||
document = loadDocument(context, inputFile);
|
||||
modifyDocument(document);
|
||||
storeDocument(document, outputFile);
|
||||
} catch (OfficeException officeException) {
|
||||
throw officeException;
|
||||
} catch (Exception exception) {
|
||||
throw new OfficeException("conversion failed", exception);
|
||||
} finally {
|
||||
if (document != null) {
|
||||
XCloseable closeable = cast(XCloseable.class, document);
|
||||
if (closeable != null) {
|
||||
try {
|
||||
closeable.close(true);
|
||||
} catch (CloseVetoException closeVetoException) {
|
||||
// whoever raised the veto should close the document
|
||||
}
|
||||
} else {
|
||||
document.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private XComponent loadDocument(OfficeContext context, File inputFile) throws OfficeException {
|
||||
if (!inputFile.exists()) {
|
||||
throw new OfficeException("input document not found");
|
||||
}
|
||||
XComponentLoader loader = cast(XComponentLoader.class, context.getService(SERVICE_DESKTOP));
|
||||
Map<String,?> loadProperties = getLoadProperties(inputFile);
|
||||
XComponent document = null;
|
||||
try {
|
||||
document = loader.loadComponentFromURL(toUrl(inputFile), "_blank", 0, toUnoProperties(loadProperties));
|
||||
} catch (IllegalArgumentException illegalArgumentException) {
|
||||
throw new OfficeException("could not load document: " + inputFile.getName(), illegalArgumentException);
|
||||
} catch (ErrorCodeIOException errorCodeIOException) {
|
||||
throw new OfficeException("could not load document: " + inputFile.getName() + "; errorCode: " + errorCodeIOException.ErrCode, errorCodeIOException);
|
||||
} catch (IOException ioException) {
|
||||
throw new OfficeException("could not load document: " + inputFile.getName(), ioException);
|
||||
}
|
||||
if (document == null) {
|
||||
throw new OfficeException("could not load document: " + inputFile.getName());
|
||||
}
|
||||
return document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to modify the document after it has been loaded and before it gets
|
||||
* saved in the new format.
|
||||
* <p>
|
||||
* Does nothing by default.
|
||||
*
|
||||
* @param document
|
||||
* @throws OfficeException
|
||||
*/
|
||||
protected void modifyDocument(XComponent document) throws OfficeException {
|
||||
// noop
|
||||
}
|
||||
|
||||
private void storeDocument(XComponent document, File outputFile) throws OfficeException {
|
||||
Map<String,?> storeProperties = getStoreProperties(outputFile, document);
|
||||
if (storeProperties == null) {
|
||||
throw new OfficeException("unsupported conversion");
|
||||
}
|
||||
try {
|
||||
cast(XStorable.class, document).storeToURL(toUrl(outputFile), toUnoProperties(storeProperties));
|
||||
} catch (ErrorCodeIOException errorCodeIOException) {
|
||||
throw new OfficeException("could not store document: " + outputFile.getName() + "; errorCode: " + errorCodeIOException.ErrCode, errorCodeIOException);
|
||||
} catch (IOException ioException) {
|
||||
throw new OfficeException("could not store document: " + outputFile.getName(), ioException);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.artofsolving.jodconverter.document.DefaultDocumentFormatRegistry;
|
||||
import org.artofsolving.jodconverter.document.DocumentFormat;
|
||||
import org.artofsolving.jodconverter.document.DocumentFormatRegistry;
|
||||
import org.artofsolving.jodconverter.office.OfficeException;
|
||||
import org.artofsolving.jodconverter.office.OfficeManager;
|
||||
|
||||
import com.sun.star.document.UpdateDocMode;
|
||||
|
||||
public class OfficeDocumentConverter {
|
||||
|
||||
private final OfficeManager officeManager;
|
||||
private final DocumentFormatRegistry formatRegistry;
|
||||
|
||||
private Map<String,?> defaultLoadProperties = createDefaultLoadProperties();
|
||||
|
||||
public OfficeDocumentConverter(OfficeManager officeManager) {
|
||||
this(officeManager, new DefaultDocumentFormatRegistry());
|
||||
}
|
||||
|
||||
public OfficeDocumentConverter(OfficeManager officeManager, DocumentFormatRegistry formatRegistry) {
|
||||
this.officeManager = officeManager;
|
||||
this.formatRegistry = formatRegistry;
|
||||
}
|
||||
|
||||
private Map<String,Object> createDefaultLoadProperties() {
|
||||
Map<String,Object> loadProperties = new HashMap<String,Object>();
|
||||
loadProperties.put("Hidden", true);
|
||||
loadProperties.put("ReadOnly", true);
|
||||
loadProperties.put("UpdateDocMode", UpdateDocMode.QUIET_UPDATE);
|
||||
return loadProperties;
|
||||
}
|
||||
|
||||
public void setDefaultLoadProperties(Map<String, ?> defaultLoadProperties) {
|
||||
this.defaultLoadProperties = defaultLoadProperties;
|
||||
}
|
||||
|
||||
public DocumentFormatRegistry getFormatRegistry() {
|
||||
return formatRegistry;
|
||||
}
|
||||
|
||||
public void convert(File inputFile, File outputFile) throws OfficeException {
|
||||
String outputExtension = FilenameUtils.getExtension(outputFile.getName());
|
||||
DocumentFormat outputFormat = formatRegistry.getFormatByExtension(outputExtension);
|
||||
convert(inputFile, outputFile, outputFormat);
|
||||
}
|
||||
|
||||
public void convert(File inputFile, File outputFile, DocumentFormat outputFormat) throws OfficeException {
|
||||
String inputExtension = FilenameUtils.getExtension(inputFile.getName());
|
||||
DocumentFormat inputFormat = formatRegistry.getFormatByExtension(inputExtension);
|
||||
StandardConversionTask conversionTask = new StandardConversionTask(inputFile, outputFile, outputFormat);
|
||||
conversionTask.setDefaultLoadProperties(defaultLoadProperties);
|
||||
conversionTask.setInputFormat(inputFormat);
|
||||
officeManager.execute(conversionTask);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter;
|
||||
|
||||
import static org.artofsolving.jodconverter.office.OfficeUtils.*;
|
||||
|
||||
import org.artofsolving.jodconverter.document.DocumentFamily;
|
||||
import org.artofsolving.jodconverter.office.OfficeException;
|
||||
|
||||
|
||||
import com.sun.star.lang.XComponent;
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
|
||||
class OfficeDocumentUtils {
|
||||
|
||||
private OfficeDocumentUtils() {
|
||||
throw new AssertionError("utility class must not be instantiated");
|
||||
}
|
||||
|
||||
public static DocumentFamily getDocumentFamily(XComponent document) throws OfficeException {
|
||||
XServiceInfo serviceInfo = cast(XServiceInfo.class, document);
|
||||
if (serviceInfo.supportsService("com.sun.star.text.GenericTextDocument")) {
|
||||
// NOTE: a GenericTextDocument is either a TextDocument, a WebDocument, or a GlobalDocument
|
||||
// but this further distinction doesn't seem to matter for conversions
|
||||
return DocumentFamily.TEXT;
|
||||
} else if (serviceInfo.supportsService("com.sun.star.sheet.SpreadsheetDocument")) {
|
||||
return DocumentFamily.SPREADSHEET;
|
||||
} else if (serviceInfo.supportsService("com.sun.star.presentation.PresentationDocument")) {
|
||||
return DocumentFamily.PRESENTATION;
|
||||
} else if (serviceInfo.supportsService("com.sun.star.drawing.DrawingDocument")) {
|
||||
return DocumentFamily.DRAWING;
|
||||
} else {
|
||||
throw new OfficeException("document of unknown family: " + serviceInfo.getImplementationName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter;
|
||||
|
||||
import static org.artofsolving.jodconverter.office.OfficeUtils.cast;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.artofsolving.jodconverter.document.DocumentFamily;
|
||||
import org.artofsolving.jodconverter.document.DocumentFormat;
|
||||
import org.artofsolving.jodconverter.office.OfficeException;
|
||||
|
||||
import com.sun.star.lang.XComponent;
|
||||
import com.sun.star.util.XRefreshable;
|
||||
|
||||
public class StandardConversionTask extends AbstractConversionTask {
|
||||
|
||||
private final DocumentFormat outputFormat;
|
||||
|
||||
private Map<String,?> defaultLoadProperties;
|
||||
private DocumentFormat inputFormat;
|
||||
|
||||
public StandardConversionTask(File inputFile, File outputFile, DocumentFormat outputFormat) {
|
||||
super(inputFile, outputFile);
|
||||
this.outputFormat = outputFormat;
|
||||
}
|
||||
|
||||
public void setDefaultLoadProperties(Map<String, ?> defaultLoadProperties) {
|
||||
this.defaultLoadProperties = defaultLoadProperties;
|
||||
}
|
||||
|
||||
public void setInputFormat(DocumentFormat inputFormat) {
|
||||
this.inputFormat = inputFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void modifyDocument(XComponent document) throws OfficeException {
|
||||
XRefreshable refreshable = cast(XRefreshable.class, document);
|
||||
if (refreshable != null) {
|
||||
refreshable.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String,?> getLoadProperties(File inputFile) {
|
||||
Map<String,Object> loadProperties = new HashMap<String,Object>();
|
||||
if (defaultLoadProperties != null) {
|
||||
loadProperties.putAll(defaultLoadProperties);
|
||||
}
|
||||
if (inputFormat != null && inputFormat.getLoadProperties() != null) {
|
||||
loadProperties.putAll(inputFormat.getLoadProperties());
|
||||
}
|
||||
return loadProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String,?> getStoreProperties(File outputFile, XComponent document) {
|
||||
DocumentFamily family = OfficeDocumentUtils.getDocumentFamily(document);
|
||||
return outputFormat.getStoreProperties(family);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.cli;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.CommandLineParser;
|
||||
import org.apache.commons.cli.HelpFormatter;
|
||||
import org.apache.commons.cli.Option;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.commons.cli.PosixParser;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.artofsolving.jodconverter.OfficeDocumentConverter;
|
||||
import org.artofsolving.jodconverter.document.DefaultDocumentFormatRegistry;
|
||||
import org.artofsolving.jodconverter.document.DocumentFormatRegistry;
|
||||
import org.artofsolving.jodconverter.document.JsonDocumentFormatRegistry;
|
||||
import org.artofsolving.jodconverter.office.OfficeManager;
|
||||
import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
|
||||
import org.json.JSONException;
|
||||
|
||||
/**
|
||||
* Command line interface executable.
|
||||
*/
|
||||
public class Convert {
|
||||
|
||||
public static final int STATUS_OK = 0;
|
||||
public static final int STATUS_MISSING_INPUT_FILE = 1;
|
||||
public static final int STATUS_INVALID_ARGUMENTS = 255;
|
||||
|
||||
private static final Option OPTION_OUTPUT_FORMAT = new Option("o", "output-format", true, "output format (e.g. pdf)");
|
||||
private static final Option OPTION_PORT = new Option("p", "port", true, "office socket port (optional; defaults to 2002)");
|
||||
private static final Option OPTION_REGISTRY = new Option("r", "registry", true, "document formats registry configuration file (optional)");
|
||||
private static final Option OPTION_TIMEOUT = new Option("t", "timeout", true, "maximum conversion time in seconds (optional; defaults to 120)");
|
||||
private static final Option OPTION_USER_PROFILE = new Option("u", "user-profile", true, "use settings from the given user installation dir (optional)");
|
||||
private static final Options OPTIONS = initOptions();
|
||||
|
||||
private static final int DEFAULT_OFFICE_PORT = 2002;
|
||||
|
||||
private static Options initOptions() {
|
||||
Options options = new Options();
|
||||
options.addOption(OPTION_OUTPUT_FORMAT);
|
||||
options.addOption(OPTION_PORT);
|
||||
options.addOption(OPTION_REGISTRY);
|
||||
options.addOption(OPTION_TIMEOUT);
|
||||
options.addOption(OPTION_USER_PROFILE);
|
||||
return options;
|
||||
}
|
||||
|
||||
public static void main(String[] arguments) throws ParseException, JSONException, IOException {
|
||||
CommandLineParser commandLineParser = new PosixParser();
|
||||
CommandLine commandLine = commandLineParser.parse(OPTIONS, arguments);
|
||||
|
||||
String outputFormat = null;
|
||||
if (commandLine.hasOption(OPTION_OUTPUT_FORMAT.getOpt())) {
|
||||
outputFormat = commandLine.getOptionValue(OPTION_OUTPUT_FORMAT.getOpt());
|
||||
}
|
||||
|
||||
int port = DEFAULT_OFFICE_PORT;
|
||||
if (commandLine.hasOption(OPTION_PORT.getOpt())) {
|
||||
port = Integer.parseInt(commandLine.getOptionValue(OPTION_PORT.getOpt()));
|
||||
}
|
||||
|
||||
String[] fileNames = commandLine.getArgs();
|
||||
if ((outputFormat == null && fileNames.length != 2) || fileNames.length < 1) {
|
||||
String syntax = "java -jar jodconverter-core.jar [options] input-file output-file\n"
|
||||
+ "or [options] -o output-format input-file [input-file...]";
|
||||
HelpFormatter helpFormatter = new HelpFormatter();
|
||||
helpFormatter.printHelp(syntax, OPTIONS);
|
||||
System.exit(STATUS_INVALID_ARGUMENTS);
|
||||
}
|
||||
|
||||
DocumentFormatRegistry registry;
|
||||
if (commandLine.hasOption(OPTION_REGISTRY.getOpt())) {
|
||||
File registryFile = new File(commandLine.getOptionValue(OPTION_REGISTRY.getOpt()));
|
||||
registry = new JsonDocumentFormatRegistry(FileUtils.readFileToString(registryFile));
|
||||
} else {
|
||||
registry = new DefaultDocumentFormatRegistry();
|
||||
}
|
||||
|
||||
DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration();
|
||||
configuration.setPortNumber(port);
|
||||
if (commandLine.hasOption(OPTION_TIMEOUT.getOpt())) {
|
||||
int timeout = Integer.parseInt(commandLine.getOptionValue(OPTION_TIMEOUT.getOpt()));
|
||||
configuration.setTaskExecutionTimeout(timeout * 1000);
|
||||
}
|
||||
if (commandLine.hasOption(OPTION_USER_PROFILE.getOpt())) {
|
||||
String templateProfileDir = commandLine.getOptionValue(OPTION_USER_PROFILE.getOpt());
|
||||
configuration.setTemplateProfileDir(new File(templateProfileDir));
|
||||
}
|
||||
|
||||
OfficeManager officeManager = configuration.buildOfficeManager();
|
||||
officeManager.start();
|
||||
OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager, registry);
|
||||
try {
|
||||
if (outputFormat == null) {
|
||||
File inputFile = new File(fileNames[0]);
|
||||
File outputFile = new File(fileNames[1]);
|
||||
converter.convert(inputFile, outputFile);
|
||||
} else {
|
||||
for (int i = 0; i < fileNames.length; i++) {
|
||||
File inputFile = new File(fileNames[i]);
|
||||
String outputName = FilenameUtils.getBaseName(fileNames[i]) + "." + outputFormat;
|
||||
File outputFile = new File(FilenameUtils.getFullPath(fileNames[i]) + outputName);
|
||||
converter.convert(inputFile, outputFile);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
officeManager.stop();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.document;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DefaultDocumentFormatRegistry extends SimpleDocumentFormatRegistry {
|
||||
|
||||
public DefaultDocumentFormatRegistry() {
|
||||
DocumentFormat pdf = new DocumentFormat("Portable Document Format", "pdf", "application/pdf");
|
||||
pdf.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "writer_pdf_Export"));
|
||||
pdf.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "calc_pdf_Export"));
|
||||
pdf.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "impress_pdf_Export"));
|
||||
pdf.setStoreProperties(DocumentFamily.DRAWING, Collections.singletonMap("FilterName", "draw_pdf_Export"));
|
||||
addFormat(pdf);
|
||||
|
||||
DocumentFormat swf = new DocumentFormat("Macromedia Flash", "swf", "application/x-shockwave-flash");
|
||||
swf.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "impress_flash_Export"));
|
||||
swf.setStoreProperties(DocumentFamily.DRAWING, Collections.singletonMap("FilterName", "draw_flash_Export"));
|
||||
addFormat(swf);
|
||||
|
||||
// disabled because it's not always available
|
||||
//DocumentFormat xhtml = new DocumentFormat("XHTML", "xhtml", "application/xhtml+xml");
|
||||
//xhtml.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "XHTML Writer File"));
|
||||
//xhtml.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "XHTML Calc File"));
|
||||
//xhtml.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "XHTML Impress File"));
|
||||
//addFormat(xhtml);
|
||||
|
||||
DocumentFormat html = new DocumentFormat("HTML", "html", "text/html");
|
||||
// HTML is treated as Text when supplied as input, but as an output it is also
|
||||
// available for exporting Spreadsheet and Presentation formats
|
||||
html.setInputFamily(DocumentFamily.TEXT);
|
||||
html.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "HTML (StarWriter)"));
|
||||
html.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "HTML (StarCalc)"));
|
||||
html.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "impress_html_Export"));
|
||||
addFormat(html);
|
||||
|
||||
DocumentFormat odt = new DocumentFormat("OpenDocument Text", "odt", "application/vnd.oasis.opendocument.text");
|
||||
odt.setInputFamily(DocumentFamily.TEXT);
|
||||
odt.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "writer8"));
|
||||
addFormat(odt);
|
||||
|
||||
DocumentFormat sxw = new DocumentFormat("OpenOffice.org 1.0 Text Document", "sxw", "application/vnd.sun.xml.writer");
|
||||
sxw.setInputFamily(DocumentFamily.TEXT);
|
||||
sxw.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "StarOffice XML (Writer)"));
|
||||
addFormat(sxw);
|
||||
|
||||
DocumentFormat doc = new DocumentFormat("Microsoft Word", "doc", "application/msword");
|
||||
doc.setInputFamily(DocumentFamily.TEXT);
|
||||
doc.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "MS Word 97"));
|
||||
addFormat(doc);
|
||||
|
||||
DocumentFormat docx = new DocumentFormat("Microsoft Word 2007 XML", "docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
||||
docx.setInputFamily(DocumentFamily.TEXT);
|
||||
addFormat(docx);
|
||||
|
||||
DocumentFormat rtf = new DocumentFormat("Rich Text Format", "rtf", "text/rtf");
|
||||
rtf.setInputFamily(DocumentFamily.TEXT);
|
||||
rtf.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "Rich Text Format"));
|
||||
addFormat(rtf);
|
||||
|
||||
DocumentFormat wpd = new DocumentFormat("WordPerfect", "wpd", "application/wordperfect");
|
||||
wpd.setInputFamily(DocumentFamily.TEXT);
|
||||
addFormat(wpd);
|
||||
|
||||
DocumentFormat txt = new DocumentFormat("Plain Text", "txt", "text/plain");
|
||||
txt.setInputFamily(DocumentFamily.TEXT);
|
||||
Map<String,Object> txtLoadAndStoreProperties = new LinkedHashMap<String,Object>();
|
||||
txtLoadAndStoreProperties.put("FilterName", "Text (encoded)");
|
||||
txtLoadAndStoreProperties.put("FilterOptions", "utf8");
|
||||
txt.setLoadProperties(txtLoadAndStoreProperties);
|
||||
txt.setStoreProperties(DocumentFamily.TEXT, txtLoadAndStoreProperties);
|
||||
addFormat(txt);
|
||||
|
||||
DocumentFormat wikitext = new DocumentFormat("MediaWiki wikitext", "wiki", "text/x-wiki");
|
||||
wikitext.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "MediaWiki"));
|
||||
//addFormat(wikitext);
|
||||
|
||||
DocumentFormat ods = new DocumentFormat("OpenDocument Spreadsheet", "ods", "application/vnd.oasis.opendocument.spreadsheet");
|
||||
ods.setInputFamily(DocumentFamily.SPREADSHEET);
|
||||
ods.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "calc8"));
|
||||
addFormat(ods);
|
||||
|
||||
DocumentFormat sxc = new DocumentFormat("OpenOffice.org 1.0 Spreadsheet", "sxc", "application/vnd.sun.xml.calc");
|
||||
sxc.setInputFamily(DocumentFamily.SPREADSHEET);
|
||||
sxc.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "StarOffice XML (Calc)"));
|
||||
addFormat(sxc);
|
||||
|
||||
DocumentFormat xls = new DocumentFormat("Microsoft Excel", "xls", "application/vnd.ms-excel");
|
||||
xls.setInputFamily(DocumentFamily.SPREADSHEET);
|
||||
xls.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "MS Excel 97"));
|
||||
addFormat(xls);
|
||||
|
||||
DocumentFormat xlsx = new DocumentFormat("Microsoft Excel 2007 XML", "xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
xlsx.setInputFamily(DocumentFamily.SPREADSHEET);
|
||||
addFormat(xlsx);
|
||||
|
||||
DocumentFormat csv = new DocumentFormat("Comma Separated Values", "csv", "text/csv");
|
||||
csv.setInputFamily(DocumentFamily.SPREADSHEET);
|
||||
Map<String,Object> csvLoadAndStoreProperties = new LinkedHashMap<String,Object>();
|
||||
csvLoadAndStoreProperties.put("FilterName", "Text - txt - csv (StarCalc)");
|
||||
csvLoadAndStoreProperties.put("FilterOptions", "44,34,0"); // Field Separator: ','; Text Delimiter: '"'
|
||||
csv.setLoadProperties(csvLoadAndStoreProperties);
|
||||
csv.setStoreProperties(DocumentFamily.SPREADSHEET, csvLoadAndStoreProperties);
|
||||
addFormat(csv);
|
||||
|
||||
DocumentFormat tsv = new DocumentFormat("Tab Separated Values", "tsv", "text/tab-separated-values");
|
||||
tsv.setInputFamily(DocumentFamily.SPREADSHEET);
|
||||
Map<String,Object> tsvLoadAndStoreProperties = new LinkedHashMap<String,Object>();
|
||||
tsvLoadAndStoreProperties.put("FilterName", "Text - txt - csv (StarCalc)");
|
||||
tsvLoadAndStoreProperties.put("FilterOptions", "9,34,0"); // Field Separator: '\t'; Text Delimiter: '"'
|
||||
tsv.setLoadProperties(tsvLoadAndStoreProperties);
|
||||
tsv.setStoreProperties(DocumentFamily.SPREADSHEET, tsvLoadAndStoreProperties);
|
||||
addFormat(tsv);
|
||||
|
||||
DocumentFormat odp = new DocumentFormat("OpenDocument Presentation", "odp", "application/vnd.oasis.opendocument.presentation");
|
||||
odp.setInputFamily(DocumentFamily.PRESENTATION);
|
||||
odp.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "impress8"));
|
||||
addFormat(odp);
|
||||
|
||||
DocumentFormat sxi = new DocumentFormat("OpenOffice.org 1.0 Presentation", "sxi", "application/vnd.sun.xml.impress");
|
||||
sxi.setInputFamily(DocumentFamily.PRESENTATION);
|
||||
sxi.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "StarOffice XML (Impress)"));
|
||||
addFormat(sxi);
|
||||
|
||||
DocumentFormat ppt = new DocumentFormat("Microsoft PowerPoint", "ppt", "application/vnd.ms-powerpoint");
|
||||
ppt.setInputFamily(DocumentFamily.PRESENTATION);
|
||||
ppt.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "MS PowerPoint 97"));
|
||||
addFormat(ppt);
|
||||
|
||||
DocumentFormat pptx = new DocumentFormat("Microsoft PowerPoint 2007 XML", "pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
|
||||
pptx.setInputFamily(DocumentFamily.PRESENTATION);
|
||||
addFormat(pptx);
|
||||
|
||||
DocumentFormat odg = new DocumentFormat("OpenDocument Drawing", "odg", "application/vnd.oasis.opendocument.graphics");
|
||||
odg.setInputFamily(DocumentFamily.DRAWING);
|
||||
odg.setStoreProperties(DocumentFamily.DRAWING, Collections.singletonMap("FilterName", "draw8"));
|
||||
addFormat(odg);
|
||||
|
||||
DocumentFormat svg = new DocumentFormat("Scalable Vector Graphics", "svg", "image/svg+xml");
|
||||
svg.setStoreProperties(DocumentFamily.DRAWING, Collections.singletonMap("FilterName", "draw_svg_Export"));
|
||||
addFormat(svg);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.document;
|
||||
|
||||
public enum DocumentFamily {
|
||||
|
||||
TEXT, SPREADSHEET, PRESENTATION, DRAWING
|
||||
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.document;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DocumentFormat {
|
||||
|
||||
private String name;
|
||||
private String extension;
|
||||
private String mediaType;
|
||||
private DocumentFamily inputFamily;
|
||||
private Map<String,?> loadProperties;
|
||||
private Map<DocumentFamily,Map<String,?>> storePropertiesByFamily;
|
||||
|
||||
public DocumentFormat() {
|
||||
// default
|
||||
}
|
||||
|
||||
public DocumentFormat(String name, String extension, String mediaType) {
|
||||
this.name = name;
|
||||
this.extension = extension;
|
||||
this.mediaType = mediaType;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getExtension() {
|
||||
return extension;
|
||||
}
|
||||
|
||||
public void setExtension(String extension) {
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
public String getMediaType() {
|
||||
return mediaType;
|
||||
}
|
||||
|
||||
public void setMediaType(String mediaType) {
|
||||
this.mediaType = mediaType;
|
||||
}
|
||||
|
||||
public DocumentFamily getInputFamily() {
|
||||
return inputFamily;
|
||||
}
|
||||
|
||||
public void setInputFamily(DocumentFamily documentFamily) {
|
||||
this.inputFamily = documentFamily;
|
||||
}
|
||||
|
||||
public Map<String, ?> getLoadProperties() {
|
||||
return loadProperties;
|
||||
}
|
||||
|
||||
public void setLoadProperties(Map<String,?> loadProperties) {
|
||||
this.loadProperties = loadProperties;
|
||||
}
|
||||
|
||||
public Map<DocumentFamily, Map<String, ?>> getStorePropertiesByFamily() {
|
||||
return storePropertiesByFamily;
|
||||
}
|
||||
|
||||
public void setStorePropertiesByFamily(Map<DocumentFamily, Map<String,?>> storePropertiesByFamily) {
|
||||
this.storePropertiesByFamily = storePropertiesByFamily;
|
||||
}
|
||||
|
||||
public void setStoreProperties(DocumentFamily family, Map<String,?> storeProperties) {
|
||||
if (storePropertiesByFamily == null) {
|
||||
storePropertiesByFamily = new HashMap<DocumentFamily,Map<String,?>>();
|
||||
}
|
||||
storePropertiesByFamily.put(family, storeProperties);
|
||||
}
|
||||
|
||||
public Map<String,?> getStoreProperties(DocumentFamily family) {
|
||||
if (storePropertiesByFamily == null) {
|
||||
return null;
|
||||
}
|
||||
return storePropertiesByFamily.get(family);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.document;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface DocumentFormatRegistry {
|
||||
|
||||
public DocumentFormat getFormatByExtension(String extension);
|
||||
|
||||
public DocumentFormat getFormatByMediaType(String mediaType);
|
||||
|
||||
public Set<DocumentFormat> getOutputFormats(DocumentFamily family);
|
||||
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.document;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class JsonDocumentFormatRegistry extends SimpleDocumentFormatRegistry {
|
||||
|
||||
public JsonDocumentFormatRegistry(InputStream input) throws JSONException, IOException {
|
||||
readJsonArray(IOUtils.toString(input));
|
||||
}
|
||||
|
||||
public JsonDocumentFormatRegistry(String source) throws JSONException {
|
||||
readJsonArray(source);
|
||||
}
|
||||
|
||||
private void readJsonArray(String source) throws JSONException {
|
||||
JSONArray array = new JSONArray(source);
|
||||
for (int i = 0; i < array.length(); i++) {
|
||||
JSONObject jsonFormat = array.getJSONObject(i);
|
||||
DocumentFormat format = new DocumentFormat();
|
||||
format.setName(jsonFormat.getString("name"));
|
||||
format.setExtension(jsonFormat.getString("extension"));
|
||||
format.setMediaType(jsonFormat.getString("mediaType"));
|
||||
if (jsonFormat.has("inputFamily")) {
|
||||
format.setInputFamily(DocumentFamily.valueOf(jsonFormat.getString("inputFamily")));
|
||||
}
|
||||
if (jsonFormat.has("loadProperties")) {
|
||||
format.setLoadProperties(toJavaMap(jsonFormat.getJSONObject("loadProperties")));
|
||||
}
|
||||
if (jsonFormat.has("storePropertiesByFamily")) {
|
||||
JSONObject jsonStorePropertiesByFamily = jsonFormat.getJSONObject("storePropertiesByFamily");
|
||||
for (String key : JSONObject.getNames(jsonStorePropertiesByFamily)) {
|
||||
Map<String,?> storeProperties = toJavaMap(jsonStorePropertiesByFamily.getJSONObject(key));
|
||||
format.setStoreProperties(DocumentFamily.valueOf(key), storeProperties);
|
||||
}
|
||||
}
|
||||
addFormat(format);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String,?> toJavaMap(JSONObject jsonMap) throws JSONException {
|
||||
Map<String,Object> map = new HashMap<String,Object>();
|
||||
for (String key : JSONObject.getNames(jsonMap)) {
|
||||
Object value = jsonMap.get(key);
|
||||
if (value instanceof JSONObject) {
|
||||
map.put(key, toJavaMap((JSONObject) value));
|
||||
} else {
|
||||
map.put(key, value);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.document;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class SimpleDocumentFormatRegistry implements DocumentFormatRegistry {
|
||||
|
||||
private List<DocumentFormat> documentFormats = new ArrayList<DocumentFormat>();
|
||||
|
||||
public void addFormat(DocumentFormat documentFormat) {
|
||||
documentFormats.add(documentFormat);
|
||||
}
|
||||
|
||||
public DocumentFormat getFormatByExtension(String extension) {
|
||||
if (extension == null) {
|
||||
return null;
|
||||
}
|
||||
String lowerExtension = extension.toLowerCase();
|
||||
//TODO keep a documentByExtension map instead
|
||||
for (DocumentFormat format : documentFormats) {
|
||||
if (format.getExtension().equals(lowerExtension)) {
|
||||
return format;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public DocumentFormat getFormatByMediaType(String mediaType) {
|
||||
if (mediaType == null) {
|
||||
return null;
|
||||
}
|
||||
//TODO keep a documentByMediaType map instead
|
||||
for (DocumentFormat format : documentFormats) {
|
||||
if (format.getMediaType().equals(mediaType)) {
|
||||
return format;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<DocumentFormat> getOutputFormats(DocumentFamily family) {
|
||||
Set<DocumentFormat> formats = new HashSet<DocumentFormat>();
|
||||
for (DocumentFormat format : documentFormats) {
|
||||
if (format.getStoreProperties(family) != null) {
|
||||
formats.add(format);
|
||||
}
|
||||
}
|
||||
return formats;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.artofsolving.jodconverter.process.ProcessManager;
|
||||
import org.artofsolving.jodconverter.process.PureJavaProcessManager;
|
||||
import org.artofsolving.jodconverter.process.LinuxProcessManager;
|
||||
import org.artofsolving.jodconverter.process.SigarProcessManager;
|
||||
import org.artofsolving.jodconverter.util.PlatformUtils;
|
||||
|
||||
public class DefaultOfficeManagerConfiguration {
|
||||
|
||||
public static final long DEFAULT_RETRY_TIMEOUT = 120000L;
|
||||
|
||||
private File officeHome = OfficeUtils.getDefaultOfficeHome();
|
||||
private OfficeConnectionProtocol connectionProtocol = OfficeConnectionProtocol.SOCKET;
|
||||
private int[] portNumbers = new int[] { 2002 };
|
||||
private String[] pipeNames = new String[] { "office" };
|
||||
private String[] runAsArgs = null;
|
||||
private File templateProfileDir = null;
|
||||
private File workDir = new File(System.getProperty("java.io.tmpdir"));
|
||||
private long taskQueueTimeout = 30000L; // 30 seconds
|
||||
private long taskExecutionTimeout = 120000L; // 2 minutes
|
||||
private int maxTasksPerProcess = 200;
|
||||
private long retryTimeout = DEFAULT_RETRY_TIMEOUT;
|
||||
|
||||
private ProcessManager processManager = null; // lazily initialised
|
||||
|
||||
public DefaultOfficeManagerConfiguration setOfficeHome(String officeHome) throws NullPointerException, IllegalArgumentException {
|
||||
checkArgumentNotNull("officeHome", officeHome);
|
||||
return setOfficeHome(new File(officeHome));
|
||||
}
|
||||
|
||||
public DefaultOfficeManagerConfiguration setOfficeHome(File officeHome) throws NullPointerException, IllegalArgumentException {
|
||||
checkArgumentNotNull("officeHome", officeHome);
|
||||
checkArgument("officeHome", officeHome.isDirectory(), "must exist and be a directory");
|
||||
this.officeHome = officeHome;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultOfficeManagerConfiguration setConnectionProtocol(OfficeConnectionProtocol connectionProtocol) throws NullPointerException {
|
||||
checkArgumentNotNull("connectionProtocol", connectionProtocol);
|
||||
this.connectionProtocol = connectionProtocol;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultOfficeManagerConfiguration setPortNumber(int portNumber) {
|
||||
this.portNumbers = new int[] { portNumber };
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultOfficeManagerConfiguration setPortNumbers(int... portNumbers) throws NullPointerException, IllegalArgumentException {
|
||||
checkArgumentNotNull("portNumbers", portNumbers);
|
||||
checkArgument("portNumbers", portNumbers.length > 0, "must not be empty");
|
||||
this.portNumbers = portNumbers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultOfficeManagerConfiguration setPipeName(String pipeName) throws NullPointerException {
|
||||
checkArgumentNotNull("pipeName", pipeName);
|
||||
this.pipeNames = new String[] { pipeName };
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultOfficeManagerConfiguration setPipeNames(String... pipeNames) throws NullPointerException, IllegalArgumentException {
|
||||
checkArgumentNotNull("pipeNames", pipeNames);
|
||||
checkArgument("pipeNames", pipeNames.length > 0, "must not be empty");
|
||||
this.pipeNames = pipeNames;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultOfficeManagerConfiguration setRunAsArgs(String... runAsArgs) {
|
||||
this.runAsArgs = runAsArgs;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultOfficeManagerConfiguration setTemplateProfileDir(File templateProfileDir) throws IllegalArgumentException {
|
||||
if (templateProfileDir != null) {
|
||||
checkArgument("templateProfileDir", templateProfileDir.isDirectory(), "must exist and be a directory");
|
||||
}
|
||||
this.templateProfileDir = templateProfileDir;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the directory where temporary office profiles will be created.
|
||||
* <p>
|
||||
* Defaults to the system temporary directory as specified by the <code>java.io.tmpdir</code> system property.
|
||||
*
|
||||
* @param workDir
|
||||
* @return
|
||||
*/
|
||||
public DefaultOfficeManagerConfiguration setWorkDir(File workDir) {
|
||||
checkArgumentNotNull("workDir", workDir);
|
||||
this.workDir = workDir;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultOfficeManagerConfiguration setTaskQueueTimeout(long taskQueueTimeout) {
|
||||
this.taskQueueTimeout = taskQueueTimeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultOfficeManagerConfiguration setTaskExecutionTimeout(long taskExecutionTimeout) {
|
||||
this.taskExecutionTimeout = taskExecutionTimeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultOfficeManagerConfiguration setMaxTasksPerProcess(int maxTasksPerProcess) {
|
||||
this.maxTasksPerProcess = maxTasksPerProcess;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a specific {@link ProcessManager} implementation
|
||||
* <p>
|
||||
* The default is to use {@link SigarProcessManager} if sigar.jar is
|
||||
* available in the classpath, otherwise {@link LinuxProcessManager}
|
||||
* on Linux and {@link PureJavaProcessManager} on other platforms.
|
||||
*
|
||||
* @param processManager
|
||||
* @return
|
||||
* @throws NullPointerException
|
||||
*/
|
||||
public DefaultOfficeManagerConfiguration setProcessManager(ProcessManager processManager) throws NullPointerException {
|
||||
checkArgumentNotNull("processManager", processManager);
|
||||
this.processManager = processManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retry timeout set in milliseconds. Used for retrying office process calls.
|
||||
* If not set, it defaults to 2 minutes
|
||||
*
|
||||
* @param retryTimeout in milliseconds
|
||||
* @return
|
||||
*/
|
||||
public DefaultOfficeManagerConfiguration setRetryTimeout(long retryTimeout) {
|
||||
this.retryTimeout = retryTimeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OfficeManager buildOfficeManager() throws IllegalStateException {
|
||||
if (officeHome == null) {
|
||||
throw new IllegalStateException("officeHome not set and could not be auto-detected");
|
||||
} else if (!officeHome.isDirectory()) {
|
||||
throw new IllegalStateException("officeHome doesn't exist or is not a directory: " + officeHome);
|
||||
} else if (!OfficeUtils.getOfficeExecutable(officeHome).isFile()) {
|
||||
throw new IllegalStateException("invalid officeHome: it doesn't contain soffice.bin: " + officeHome);
|
||||
}
|
||||
if (templateProfileDir != null && !isValidProfileDir(templateProfileDir)) {
|
||||
throw new IllegalStateException("templateProfileDir doesn't appear to contain a user profile: " + templateProfileDir);
|
||||
}
|
||||
if (!workDir.isDirectory()) {
|
||||
throw new IllegalStateException("workDir doesn't exist or is not a directory: " + workDir);
|
||||
}
|
||||
|
||||
if (processManager == null) {
|
||||
processManager = findBestProcessManager();
|
||||
}
|
||||
|
||||
int numInstances = connectionProtocol == OfficeConnectionProtocol.PIPE ? pipeNames.length : portNumbers.length;
|
||||
UnoUrl[] unoUrls = new UnoUrl[numInstances];
|
||||
for (int i = 0; i < numInstances; i++) {
|
||||
unoUrls[i] = (connectionProtocol == OfficeConnectionProtocol.PIPE) ? UnoUrl.pipe(pipeNames[i]) : UnoUrl.socket(portNumbers[i]);
|
||||
}
|
||||
return new ProcessPoolOfficeManager(officeHome, unoUrls, runAsArgs, templateProfileDir, workDir, retryTimeout, taskQueueTimeout, taskExecutionTimeout, maxTasksPerProcess, processManager);
|
||||
}
|
||||
|
||||
private ProcessManager findBestProcessManager() {
|
||||
if (isSigarAvailable()) {
|
||||
return new SigarProcessManager();
|
||||
} else if (PlatformUtils.isLinux()) {
|
||||
LinuxProcessManager processManager = new LinuxProcessManager();
|
||||
if (runAsArgs != null) {
|
||||
processManager.setRunAsArgs(runAsArgs);
|
||||
}
|
||||
return processManager;
|
||||
} else {
|
||||
// NOTE: UnixProcessManager can't be trusted to work on Solaris
|
||||
// because of the 80-char limit on ps output there
|
||||
return new PureJavaProcessManager();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSigarAvailable() {
|
||||
try {
|
||||
Class.forName("org.hyperic.sigar.Sigar", false, getClass().getClassLoader());
|
||||
return true;
|
||||
} catch (ClassNotFoundException classNotFoundException) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkArgumentNotNull(String argName, Object argValue) throws NullPointerException {
|
||||
if (argValue == null) {
|
||||
throw new NullPointerException(argName + " must not be null");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkArgument(String argName, boolean condition, String message) throws IllegalArgumentException {
|
||||
if (!condition) {
|
||||
throw new IllegalArgumentException(argName + " " + message);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidProfileDir(File profileDir) {
|
||||
return new File(profileDir, "user").isDirectory();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import java.net.ConnectException;
|
||||
|
||||
/**
|
||||
* {@link OfficeManager} implementation that connects to an external Office process.
|
||||
* <p>
|
||||
* The external Office process needs to be started manually, e.g. from the command line with
|
||||
*
|
||||
* <pre>
|
||||
* soffice -accept="socket,host=127.0.0.1,port=2002;urp;"
|
||||
* </pre>
|
||||
* <p>
|
||||
* Since this implementation does not manage the Office process, it does not support auto-restarting the process if it exits unexpectedly.
|
||||
* <p>
|
||||
* It will however auto-reconnect to the external process if the latter is manually restarted.
|
||||
* <p>
|
||||
* This {@link OfficeManager} implementation basically provides the same behaviour as JODConverter 2.x, including using <em>synchronized</em> blocks for serialising office
|
||||
* operations.
|
||||
*/
|
||||
class ExternalOfficeManager implements OfficeManager {
|
||||
|
||||
private final OfficeConnection connection;
|
||||
private final boolean connectOnStart;
|
||||
|
||||
/**
|
||||
* @param unoUrl
|
||||
* @param connectOnStart
|
||||
* should a connection be attempted on {@link #start()}? Default is <em>true</em>. If <em>false</em>, a connection will only be attempted the first time an
|
||||
* {@link OfficeTask} is executed.
|
||||
*/
|
||||
public ExternalOfficeManager(UnoUrl unoUrl, boolean connectOnStart) {
|
||||
connection = new OfficeConnection(unoUrl);
|
||||
this.connectOnStart = connectOnStart;
|
||||
}
|
||||
|
||||
public void start() throws OfficeException {
|
||||
if (connectOnStart) {
|
||||
synchronized (connection) {
|
||||
connect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
synchronized (connection) {
|
||||
if (connection.isConnected()) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void execute(OfficeTask task) throws OfficeException {
|
||||
synchronized (connection) {
|
||||
if (!connection.isConnected()) {
|
||||
connect();
|
||||
}
|
||||
task.execute(connection);
|
||||
}
|
||||
}
|
||||
|
||||
private void connect() {
|
||||
try {
|
||||
connection.connect();
|
||||
} catch (ConnectException connectException) {
|
||||
throw new OfficeException("could not connect to external office process", connectException);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return connection.isConnected();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
public class ExternalOfficeManagerConfiguration {
|
||||
|
||||
private OfficeConnectionProtocol connectionProtocol = OfficeConnectionProtocol.SOCKET;
|
||||
private int portNumber = 2002;
|
||||
private String pipeName = "office";
|
||||
private boolean connectOnStart = true;
|
||||
|
||||
public ExternalOfficeManagerConfiguration setConnectionProtocol(OfficeConnectionProtocol connectionProtocol) {
|
||||
this.connectionProtocol = connectionProtocol;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExternalOfficeManagerConfiguration setPortNumber(int portNumber) {
|
||||
this.portNumber = portNumber;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExternalOfficeManagerConfiguration setPipeName(String pipeName) {
|
||||
this.pipeName = pipeName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExternalOfficeManagerConfiguration setConnectOnStart(boolean connectOnStart) {
|
||||
this.connectOnStart = connectOnStart;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OfficeManager buildOfficeManager() {
|
||||
UnoUrl unoUrl = connectionProtocol == OfficeConnectionProtocol.SOCKET ? UnoUrl.socket(portNumber) : UnoUrl.pipe(pipeName);
|
||||
return new ExternalOfficeManager(unoUrl, connectOnStart);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,176 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sun.star.frame.XDesktop;
|
||||
import com.sun.star.lang.DisposedException;
|
||||
|
||||
class ManagedOfficeProcess {
|
||||
|
||||
private static final Integer EXIT_CODE_NEW_INSTALLATION = Integer.valueOf(81);
|
||||
|
||||
private final ManagedOfficeProcessSettings settings;
|
||||
|
||||
private final OfficeProcess process;
|
||||
private final OfficeConnection connection;
|
||||
|
||||
private ExecutorService executor = Executors.newSingleThreadExecutor(new NamedThreadFactory("OfficeProcessThread"));
|
||||
|
||||
private final Logger logger = Logger.getLogger(getClass().getName());
|
||||
|
||||
public ManagedOfficeProcess(ManagedOfficeProcessSettings settings) throws OfficeException {
|
||||
this.settings = settings;
|
||||
process = new OfficeProcess(settings.getOfficeHome(), settings.getUnoUrl(), settings.getRunAsArgs(), settings.getTemplateProfileDir(), settings.getWorkDir(), settings
|
||||
.getProcessManager());
|
||||
connection = new OfficeConnection(settings.getUnoUrl());
|
||||
}
|
||||
|
||||
public OfficeConnection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void startAndWait() throws OfficeException {
|
||||
Future<?> future = executor.submit(new Runnable() {
|
||||
public void run() {
|
||||
doStartProcessAndConnect();
|
||||
}
|
||||
});
|
||||
try {
|
||||
future.get();
|
||||
} catch (Exception exception) {
|
||||
throw new OfficeException("failed to start and connect", exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopAndWait() throws OfficeException {
|
||||
Future<?> future = executor.submit(new Runnable() {
|
||||
public void run() {
|
||||
doStopProcess();
|
||||
}
|
||||
});
|
||||
try {
|
||||
future.get();
|
||||
} catch (Exception exception) {
|
||||
throw new OfficeException("failed to start and connect", exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void restartAndWait() {
|
||||
Future<?> future = executor.submit(new Runnable() {
|
||||
public void run() {
|
||||
doStopProcess();
|
||||
doStartProcessAndConnect();
|
||||
}
|
||||
});
|
||||
try {
|
||||
future.get();
|
||||
} catch (Exception exception) {
|
||||
throw new OfficeException("failed to restart", exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void restartDueToTaskTimeout() {
|
||||
executor.execute(new Runnable() {
|
||||
public void run() {
|
||||
doTerminateProcess();
|
||||
// will cause unexpected disconnection and subsequent restart
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void restartDueToLostConnection() {
|
||||
executor.execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
doEnsureProcessExited();
|
||||
doStartProcessAndConnect();
|
||||
} catch (OfficeException officeException) {
|
||||
logger.log(Level.SEVERE, "could not restart process", officeException);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void doStartProcessAndConnect() throws OfficeException {
|
||||
try {
|
||||
process.start();
|
||||
new Retryable() {
|
||||
protected void attempt() throws TemporaryException, Exception {
|
||||
try {
|
||||
connection.connect();
|
||||
} catch (ConnectException connectException) {
|
||||
Integer exitCode = process.getExitCode();
|
||||
if (exitCode == null) {
|
||||
// process is running; retry later
|
||||
throw new TemporaryException(connectException);
|
||||
} else if (exitCode.equals(EXIT_CODE_NEW_INSTALLATION)) {
|
||||
// restart and retry later
|
||||
// see http://code.google.com/p/jodconverter/issues/detail?id=84
|
||||
logger.log(Level.WARNING, "office process died with exit code 81; restarting it");
|
||||
process.start(true);
|
||||
throw new TemporaryException(connectException);
|
||||
} else {
|
||||
throw new OfficeException("office process died with exit code " + exitCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.execute(settings.getRetryInterval(), settings.getRetryTimeout());
|
||||
} catch (Exception exception) {
|
||||
throw new OfficeException("could not establish connection", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private void doStopProcess() {
|
||||
try {
|
||||
XDesktop desktop = OfficeUtils.cast(XDesktop.class, connection.getService(OfficeUtils.SERVICE_DESKTOP));
|
||||
desktop.terminate();
|
||||
} catch (DisposedException disposedException) {
|
||||
// expected
|
||||
} catch (Exception exception) {
|
||||
// in case we can't get hold of the desktop
|
||||
doTerminateProcess();
|
||||
}
|
||||
doEnsureProcessExited();
|
||||
}
|
||||
|
||||
private void doEnsureProcessExited() throws OfficeException {
|
||||
try {
|
||||
int exitCode = process.getExitCode(settings.getRetryInterval(), settings.getRetryTimeout());
|
||||
logger.info("process exited with code " + exitCode);
|
||||
} catch (RetryTimeoutException retryTimeoutException) {
|
||||
doTerminateProcess();
|
||||
}
|
||||
process.deleteProfileDir();
|
||||
}
|
||||
|
||||
private void doTerminateProcess() throws OfficeException {
|
||||
try {
|
||||
int exitCode = process.forciblyTerminate(settings.getRetryInterval(), settings.getRetryTimeout());
|
||||
logger.info("process forcibly terminated with code " + exitCode);
|
||||
} catch (Exception exception) {
|
||||
throw new OfficeException("could not terminate process", exception);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isConnected() {
|
||||
return connection.isConnected();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.artofsolving.jodconverter.process.ProcessManager;
|
||||
import org.artofsolving.jodconverter.process.PureJavaProcessManager;
|
||||
|
||||
class ManagedOfficeProcessSettings {
|
||||
|
||||
public static final long DEFAULT_RETRY_INTERVAL = 250L;
|
||||
|
||||
private final UnoUrl unoUrl;
|
||||
private File officeHome = OfficeUtils.getDefaultOfficeHome();
|
||||
private String[] runAsArgs;
|
||||
private File templateProfileDir;
|
||||
private File workDir = new File(System.getProperty("java.io.tmpdir"));
|
||||
private ProcessManager processManager = new PureJavaProcessManager();
|
||||
private long retryTimeout = DefaultOfficeManagerConfiguration.DEFAULT_RETRY_TIMEOUT;
|
||||
private long retryInterval = DEFAULT_RETRY_INTERVAL;
|
||||
|
||||
public ManagedOfficeProcessSettings(UnoUrl unoUrl) {
|
||||
this.unoUrl = unoUrl;
|
||||
}
|
||||
|
||||
public UnoUrl getUnoUrl() {
|
||||
return unoUrl;
|
||||
}
|
||||
|
||||
public File getOfficeHome() {
|
||||
return officeHome;
|
||||
}
|
||||
|
||||
public void setOfficeHome(File officeHome) {
|
||||
this.officeHome = officeHome;
|
||||
}
|
||||
|
||||
public String[] getRunAsArgs() {
|
||||
return runAsArgs;
|
||||
}
|
||||
|
||||
public void setRunAsArgs(String[] runAsArgs) {
|
||||
this.runAsArgs = runAsArgs;
|
||||
}
|
||||
|
||||
public File getTemplateProfileDir() {
|
||||
return templateProfileDir;
|
||||
}
|
||||
|
||||
public void setTemplateProfileDir(File templateProfileDir) {
|
||||
this.templateProfileDir = templateProfileDir;
|
||||
}
|
||||
|
||||
public File getWorkDir() {
|
||||
return workDir;
|
||||
}
|
||||
|
||||
public void setWorkDir(File workDir) {
|
||||
this.workDir = workDir;
|
||||
}
|
||||
|
||||
public ProcessManager getProcessManager() {
|
||||
return processManager;
|
||||
}
|
||||
|
||||
public void setProcessManager(ProcessManager processManager) {
|
||||
this.processManager = processManager;
|
||||
}
|
||||
|
||||
public long getRetryTimeout() {
|
||||
return retryTimeout;
|
||||
}
|
||||
|
||||
public void setRetryTimeout(long retryTimeout) {
|
||||
this.retryTimeout = retryTimeout;
|
||||
}
|
||||
|
||||
public long getRetryInterval() {
|
||||
return retryInterval;
|
||||
}
|
||||
|
||||
public void setRetryInterval(long retryInterval) {
|
||||
this.retryInterval = retryInterval;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A {@link ThreadFactory} that allows for custom thread names
|
||||
*/
|
||||
class NamedThreadFactory implements ThreadFactory {
|
||||
|
||||
private static final AtomicInteger threadIndex = new AtomicInteger(0);
|
||||
|
||||
private final String baseName;
|
||||
private final boolean daemon;
|
||||
|
||||
public NamedThreadFactory(String baseName) {
|
||||
this(baseName, true);
|
||||
}
|
||||
|
||||
public NamedThreadFactory(String baseName, boolean daemon) {
|
||||
this.baseName = baseName;
|
||||
this.daemon = daemon;
|
||||
}
|
||||
|
||||
public Thread newThread(Runnable runnable) {
|
||||
Thread thread = new Thread(runnable, baseName + "-" + threadIndex.getAndIncrement());
|
||||
thread.setDaemon(daemon);
|
||||
return thread;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
import com.sun.star.bridge.XBridge;
|
||||
import com.sun.star.bridge.XBridgeFactory;
|
||||
import com.sun.star.comp.helper.Bootstrap;
|
||||
import com.sun.star.connection.NoConnectException;
|
||||
import com.sun.star.connection.XConnection;
|
||||
import com.sun.star.connection.XConnector;
|
||||
import com.sun.star.lang.EventObject;
|
||||
import com.sun.star.lang.XComponent;
|
||||
import com.sun.star.lang.XEventListener;
|
||||
import com.sun.star.lang.XMultiComponentFactory;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
class OfficeConnection implements OfficeContext {
|
||||
|
||||
private static AtomicInteger bridgeIndex = new AtomicInteger();
|
||||
|
||||
private final UnoUrl unoUrl;
|
||||
|
||||
private XComponent bridgeComponent;
|
||||
private XMultiComponentFactory serviceManager;
|
||||
private XComponentContext componentContext;
|
||||
|
||||
private final List<OfficeConnectionEventListener> connectionEventListeners = new ArrayList<OfficeConnectionEventListener>();
|
||||
|
||||
private volatile boolean connected = false;
|
||||
|
||||
private XEventListener bridgeListener = new XEventListener() {
|
||||
public void disposing(EventObject event) {
|
||||
if (connected) {
|
||||
connected = false;
|
||||
logger.info(String.format("disconnected: '%s'", unoUrl));
|
||||
OfficeConnectionEvent connectionEvent = new OfficeConnectionEvent(OfficeConnection.this);
|
||||
for (OfficeConnectionEventListener listener : connectionEventListeners) {
|
||||
listener.disconnected(connectionEvent);
|
||||
}
|
||||
}
|
||||
// else we tried to connect to a server that doesn't speak URP
|
||||
}
|
||||
};
|
||||
|
||||
private final Logger logger = Logger.getLogger(getClass().getName());
|
||||
|
||||
public OfficeConnection(UnoUrl unoUrl) {
|
||||
this.unoUrl = unoUrl;
|
||||
}
|
||||
|
||||
public void addConnectionEventListener(OfficeConnectionEventListener connectionEventListener) {
|
||||
connectionEventListeners.add(connectionEventListener);
|
||||
}
|
||||
|
||||
public void connect() throws ConnectException {
|
||||
logger.fine(String.format("connecting with connectString '%s'", unoUrl));
|
||||
try {
|
||||
XComponentContext localContext = Bootstrap.createInitialComponentContext(null);
|
||||
XMultiComponentFactory localServiceManager = localContext.getServiceManager();
|
||||
XConnector connector = OfficeUtils.cast(XConnector.class, localServiceManager.createInstanceWithContext("com.sun.star.connection.Connector", localContext));
|
||||
XConnection connection = connector.connect(unoUrl.getConnectString());
|
||||
XBridgeFactory bridgeFactory = OfficeUtils.cast(XBridgeFactory.class, localServiceManager.createInstanceWithContext("com.sun.star.bridge.BridgeFactory", localContext));
|
||||
String bridgeName = "jodconverter_" + bridgeIndex.getAndIncrement();
|
||||
XBridge bridge = bridgeFactory.createBridge(bridgeName, "urp", connection, null);
|
||||
bridgeComponent = OfficeUtils.cast(XComponent.class, bridge);
|
||||
bridgeComponent.addEventListener(bridgeListener);
|
||||
serviceManager = OfficeUtils.cast(XMultiComponentFactory.class, bridge.getInstance("StarOffice.ServiceManager"));
|
||||
XPropertySet properties = OfficeUtils.cast(XPropertySet.class, serviceManager);
|
||||
componentContext = OfficeUtils.cast(XComponentContext.class, properties.getPropertyValue("DefaultContext"));
|
||||
connected = true;
|
||||
logger.info(String.format("connected: '%s'", unoUrl));
|
||||
OfficeConnectionEvent connectionEvent = new OfficeConnectionEvent(this);
|
||||
for (OfficeConnectionEventListener listener : connectionEventListeners) {
|
||||
listener.connected(connectionEvent);
|
||||
}
|
||||
} catch (NoConnectException connectException) {
|
||||
throw new ConnectException(String.format("connection failed: '%s'; %s", unoUrl, connectException.getMessage()));
|
||||
} catch (Exception exception) {
|
||||
throw new OfficeException("connection failed: "+ unoUrl, exception);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
public synchronized void disconnect() {
|
||||
logger.fine(String.format("disconnecting: '%s'", unoUrl));
|
||||
bridgeComponent.dispose();
|
||||
}
|
||||
|
||||
public Object getService(String serviceName) {
|
||||
try {
|
||||
return serviceManager.createInstanceWithContext(serviceName, componentContext);
|
||||
} catch (Exception exception) {
|
||||
throw new OfficeException(String.format("failed to obtain service '%s'", serviceName), exception);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
class OfficeConnectionEvent extends EventObject {
|
||||
|
||||
private static final long serialVersionUID = 2060652797570876077L;
|
||||
|
||||
public OfficeConnectionEvent(OfficeConnection source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import java.util.EventListener;
|
||||
|
||||
interface OfficeConnectionEventListener extends EventListener {
|
||||
|
||||
void connected(OfficeConnectionEvent event);
|
||||
|
||||
void disconnected(OfficeConnectionEvent event);
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
public enum OfficeConnectionProtocol { PIPE, SOCKET }
|
@ -0,0 +1,19 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
public interface OfficeContext {
|
||||
|
||||
Object getService(String serviceName);
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
public class OfficeException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public OfficeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public OfficeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
/**
|
||||
* An OfficeManager knows how to execute {@link OfficeTask}s.
|
||||
* <p>
|
||||
* An OfficeManager implementation will typically manage one or more
|
||||
* {@link OfficeConnection}s.
|
||||
*/
|
||||
public interface OfficeManager {
|
||||
|
||||
void execute(OfficeTask task) throws OfficeException;
|
||||
|
||||
void start() throws OfficeException;
|
||||
|
||||
void stop() throws OfficeException;
|
||||
|
||||
boolean isRunning();
|
||||
}
|
@ -0,0 +1,209 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import static org.artofsolving.jodconverter.process.ProcessManager.PID_NOT_FOUND;
|
||||
import static org.artofsolving.jodconverter.process.ProcessManager.PID_UNKNOWN;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.artofsolving.jodconverter.process.ProcessManager;
|
||||
import org.artofsolving.jodconverter.process.ProcessQuery;
|
||||
import org.artofsolving.jodconverter.util.PlatformUtils;
|
||||
|
||||
class OfficeProcess {
|
||||
|
||||
private final File officeHome;
|
||||
private final UnoUrl unoUrl;
|
||||
private final String[] runAsArgs;
|
||||
private final File templateProfileDir;
|
||||
private final File instanceProfileDir;
|
||||
private final ProcessManager processManager;
|
||||
|
||||
private Process process;
|
||||
private long pid = PID_UNKNOWN;
|
||||
|
||||
private final Logger logger = Logger.getLogger(getClass().getName());
|
||||
|
||||
public OfficeProcess(File officeHome, UnoUrl unoUrl, String[] runAsArgs, File templateProfileDir, File workDir, ProcessManager processManager) {
|
||||
this.officeHome = officeHome;
|
||||
this.unoUrl = unoUrl;
|
||||
this.runAsArgs = runAsArgs;
|
||||
this.templateProfileDir = templateProfileDir;
|
||||
this.instanceProfileDir = getInstanceProfileDir(workDir, unoUrl);
|
||||
this.processManager = processManager;
|
||||
}
|
||||
|
||||
public void start() throws IOException {
|
||||
start(false);
|
||||
}
|
||||
|
||||
public void start(boolean restart) throws IOException {
|
||||
ProcessQuery processQuery = new ProcessQuery("soffice.bin", unoUrl.getAcceptString());
|
||||
long existingPid = processManager.findPid(processQuery);
|
||||
if (!(existingPid == PID_NOT_FOUND || existingPid == PID_UNKNOWN)) {
|
||||
throw new IllegalStateException(String.format("a process with acceptString '%s' is already running; pid %d",
|
||||
unoUrl.getAcceptString(), existingPid));
|
||||
}
|
||||
if (!restart) {
|
||||
prepareInstanceProfileDir();
|
||||
}
|
||||
List<String> command = new ArrayList<String>();
|
||||
File executable = OfficeUtils.getOfficeExecutable(officeHome);
|
||||
if (runAsArgs != null) {
|
||||
command.addAll(Arrays.asList(runAsArgs));
|
||||
}
|
||||
command.add(executable.getAbsolutePath());
|
||||
command.add("-accept=" + unoUrl.getAcceptString() + ";urp;");
|
||||
command.add("-env:UserInstallation=" + OfficeUtils.toUrl(instanceProfileDir));
|
||||
command.add("-headless");
|
||||
command.add("-nocrashreport");
|
||||
command.add("-nodefault");
|
||||
command.add("-nofirststartwizard");
|
||||
command.add("-nolockcheck");
|
||||
command.add("-nologo");
|
||||
command.add("-norestore");
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||
if (PlatformUtils.isWindows()) {
|
||||
addBasisAndUrePaths(processBuilder);
|
||||
}
|
||||
logger.info(String.format("starting process with acceptString '%s' and profileDir '%s'", unoUrl, instanceProfileDir));
|
||||
process = processBuilder.start();
|
||||
pid = processManager.findPid(processQuery);
|
||||
if (pid == PID_NOT_FOUND) {
|
||||
throw new IllegalStateException(String.format("process with acceptString '%s' started but its pid could not be found",
|
||||
unoUrl.getAcceptString()));
|
||||
}
|
||||
logger.info("started process" + (pid != PID_UNKNOWN ? "; pid = " + pid : ""));
|
||||
}
|
||||
|
||||
private File getInstanceProfileDir(File workDir, UnoUrl unoUrl) {
|
||||
String dirName = ".jodconverter_" + unoUrl.getAcceptString().replace(',', '_').replace('=', '-');
|
||||
return new File(workDir, dirName);
|
||||
}
|
||||
|
||||
private void prepareInstanceProfileDir() throws OfficeException {
|
||||
if (instanceProfileDir.exists()) {
|
||||
logger.warning(String.format("profile dir '%s' already exists; deleting", instanceProfileDir));
|
||||
deleteProfileDir();
|
||||
}
|
||||
if (templateProfileDir != null) {
|
||||
try {
|
||||
FileUtils.copyDirectory(templateProfileDir, instanceProfileDir);
|
||||
} catch (IOException ioException) {
|
||||
throw new OfficeException("failed to create profileDir", ioException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteProfileDir() {
|
||||
if (instanceProfileDir != null) {
|
||||
try {
|
||||
FileUtils.deleteDirectory(instanceProfileDir);
|
||||
} catch (IOException ioException) {
|
||||
File oldProfileDir = new File(instanceProfileDir.getParentFile(), instanceProfileDir.getName() + ".old." + System.currentTimeMillis());
|
||||
if (instanceProfileDir.renameTo(oldProfileDir)) {
|
||||
logger.warning("could not delete profileDir: " + ioException.getMessage() + "; renamed it to " + oldProfileDir);
|
||||
} else {
|
||||
logger.severe("could not delete profileDir: " + ioException.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addBasisAndUrePaths(ProcessBuilder processBuilder) throws IOException {
|
||||
// see http://wiki.services.openoffice.org/wiki/ODF_Toolkit/Efforts/Three-Layer_OOo
|
||||
File basisLink = new File(officeHome, "basis-link");
|
||||
if (!basisLink.isFile()) {
|
||||
logger.fine("no %OFFICE_HOME%/basis-link found; assuming it's OOo 2.x and we don't need to append URE and Basic paths");
|
||||
return;
|
||||
}
|
||||
String basisLinkText = FileUtils.readFileToString(basisLink).trim();
|
||||
File basisHome = new File(officeHome, basisLinkText);
|
||||
File basisProgram = new File(basisHome, "program");
|
||||
File ureLink = new File(basisHome, "ure-link");
|
||||
String ureLinkText = FileUtils.readFileToString(ureLink).trim();
|
||||
File ureHome = new File(basisHome, ureLinkText);
|
||||
File ureBin = new File(ureHome, "bin");
|
||||
Map<String,String> environment = processBuilder.environment();
|
||||
// Windows environment variables are case insensitive but Java maps are not :-/
|
||||
// so let's make sure we modify the existing key
|
||||
String pathKey = "PATH";
|
||||
for (String key : environment.keySet()) {
|
||||
if ("PATH".equalsIgnoreCase(key)) {
|
||||
pathKey = key;
|
||||
}
|
||||
}
|
||||
String path = environment.get(pathKey) + ";" + ureBin.getAbsolutePath() + ";" + basisProgram.getAbsolutePath();
|
||||
logger.fine(String.format("setting %s to \"%s\"", pathKey, path));
|
||||
environment.put(pathKey, path);
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
if (process == null) {
|
||||
return false;
|
||||
}
|
||||
return getExitCode() == null;
|
||||
}
|
||||
|
||||
private class ExitCodeRetryable extends Retryable {
|
||||
|
||||
private int exitCode;
|
||||
|
||||
protected void attempt() throws TemporaryException, Exception {
|
||||
try {
|
||||
exitCode = process.exitValue();
|
||||
} catch (IllegalThreadStateException illegalThreadStateException) {
|
||||
throw new TemporaryException(illegalThreadStateException);
|
||||
}
|
||||
}
|
||||
|
||||
public int getExitCode() {
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Integer getExitCode() {
|
||||
try {
|
||||
return process.exitValue();
|
||||
} catch (IllegalThreadStateException exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int getExitCode(long retryInterval, long retryTimeout) throws RetryTimeoutException {
|
||||
try {
|
||||
ExitCodeRetryable retryable = new ExitCodeRetryable();
|
||||
retryable.execute(retryInterval, retryTimeout);
|
||||
return retryable.getExitCode();
|
||||
} catch (RetryTimeoutException retryTimeoutException) {
|
||||
throw retryTimeoutException;
|
||||
} catch (Exception exception) {
|
||||
throw new OfficeException("could not get process exit code", exception);
|
||||
}
|
||||
}
|
||||
|
||||
public int forciblyTerminate(long retryInterval, long retryTimeout) throws IOException, RetryTimeoutException {
|
||||
logger.info(String.format("trying to forcibly terminate process: '" + unoUrl + "'" + (pid != PID_UNKNOWN ? " (pid " + pid + ")" : "")));
|
||||
processManager.kill(process, pid);
|
||||
return getExitCode(retryInterval, retryTimeout);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
public interface OfficeTask {
|
||||
|
||||
void execute(OfficeContext context) throws OfficeException;
|
||||
|
||||
}
|
@ -0,0 +1,183 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.artofsolving.jodconverter.util.PlatformUtils;
|
||||
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
|
||||
public class OfficeUtils {
|
||||
|
||||
public static final String SERVICE_DESKTOP = "com.sun.star.frame.Desktop";
|
||||
public static final String OFFICE_HOME_KEY = "office.home";
|
||||
public static final String DEFAULT_OFFICE_HOME_VALUE = "default";
|
||||
|
||||
private OfficeUtils() {
|
||||
throw new AssertionError("utility class must not be instantiated");
|
||||
}
|
||||
|
||||
public static <T> T cast(Class<T> type, Object object) {
|
||||
return (T) UnoRuntime.queryInterface(type, object);
|
||||
}
|
||||
|
||||
public static PropertyValue property(String name, Object value) {
|
||||
PropertyValue propertyValue = new PropertyValue();
|
||||
propertyValue.Name = name;
|
||||
propertyValue.Value = value;
|
||||
return propertyValue;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static PropertyValue[] toUnoProperties(Map<String,?> properties) {
|
||||
PropertyValue[] propertyValues = new PropertyValue[properties.size()];
|
||||
int i = 0;
|
||||
for (Map.Entry<String,?> entry : properties.entrySet()) {
|
||||
Object value = entry.getValue();
|
||||
if (value instanceof Map) {
|
||||
Map<String,Object> subProperties = (Map<String,Object>) value;
|
||||
value = toUnoProperties(subProperties);
|
||||
}
|
||||
propertyValues[i++] = property((String) entry.getKey(), value);
|
||||
}
|
||||
return propertyValues;
|
||||
}
|
||||
|
||||
public static String toUrl(File file) {
|
||||
String path = file.toURI().getRawPath();
|
||||
String url = path.startsWith("//") ? "file:" + path : "file://" + path;
|
||||
return url.endsWith("/") ? url.substring(0, url.length() - 1) : url;
|
||||
}
|
||||
|
||||
public static File getDefaultOfficeHome() {
|
||||
Properties properties = new Properties();
|
||||
String customizedConfigPath = getCustomizedConfigPath();
|
||||
try {
|
||||
BufferedReader bufferedReader = new BufferedReader(new FileReader(customizedConfigPath));
|
||||
properties.load(bufferedReader);
|
||||
restorePropertiesFromEnvFormat(properties);
|
||||
} catch (Exception e) {}
|
||||
String officeHome = properties.getProperty(OFFICE_HOME_KEY);
|
||||
if (officeHome != null && !DEFAULT_OFFICE_HOME_VALUE.equals(officeHome)) {
|
||||
return new File(officeHome);
|
||||
}
|
||||
if (PlatformUtils.isWindows()) {
|
||||
// %ProgramFiles(x86)% on 64-bit machines; %ProgramFiles% on 32-bit ones
|
||||
String homePath = OfficeUtils.getHomePath();
|
||||
String programFiles = System.getenv("ProgramFiles(x86)");
|
||||
if (programFiles == null) {
|
||||
programFiles = System.getenv("ProgramFiles");
|
||||
}
|
||||
return findOfficeHome(
|
||||
programFiles + File.separator + "OpenOffice 4",
|
||||
programFiles + File.separator + "LibreOffice 4",
|
||||
homePath + File.separator + "office"
|
||||
);
|
||||
} else if (PlatformUtils.isMac()) {
|
||||
return findOfficeHome(
|
||||
"/Applications/OpenOffice.org.app/Contents",
|
||||
"/Applications/OpenOffice.app/Contents",
|
||||
"/Applications/LibreOffice.app/Contents"
|
||||
);
|
||||
} else {
|
||||
// Linux or other *nix variants
|
||||
return findOfficeHome(
|
||||
"/opt/openoffice.org3",
|
||||
"/opt/openoffice",
|
||||
"/opt/libreoffice",
|
||||
"/opt/openoffice4",
|
||||
"/usr/lib/openoffice",
|
||||
"/usr/lib/libreoffice"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static File findOfficeHome(String... knownPaths) {
|
||||
for (String path : knownPaths) {
|
||||
File home = new File(path);
|
||||
if (getOfficeExecutable(home).isFile()) {
|
||||
return home;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static File getOfficeExecutable(File officeHome) {
|
||||
if (PlatformUtils.isMac()) {
|
||||
return new File(officeHome, "MacOS/soffice");
|
||||
} else {
|
||||
return new File(officeHome, "program/soffice.bin");
|
||||
}
|
||||
}
|
||||
|
||||
public static String getHomePath() {
|
||||
String userDir = System.getenv("KKFILEVIEW_BIN_FOLDER");
|
||||
if (userDir == null) {
|
||||
userDir = System.getProperty("user.dir");
|
||||
}
|
||||
if (userDir.endsWith("bin")) {
|
||||
userDir = userDir.substring(0, userDir.length() - 4);
|
||||
} else {
|
||||
String separator = File.separator;
|
||||
if (userDir.contains("jodconverter-web")) {
|
||||
userDir = userDir + separator + "src" + separator + "main";
|
||||
} else {
|
||||
userDir = userDir + separator + "jodconverter-web" + separator + "src" + separator + "main";
|
||||
}
|
||||
}
|
||||
return userDir;
|
||||
}
|
||||
|
||||
public static String getCustomizedConfigPath() {
|
||||
String homePath = OfficeUtils.getHomePath();
|
||||
String separator = java.io.File.separator;
|
||||
String configFilePath = homePath + separator + "config" + separator + "application.properties";
|
||||
return configFilePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* SpringBoot application.properties 支持从环境变量获取值
|
||||
* @param properties
|
||||
*/
|
||||
public synchronized static void restorePropertiesFromEnvFormat(Properties properties) {
|
||||
Iterator<Map.Entry<Object, Object>> iterator = properties.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<Object, Object> entry = iterator.next();
|
||||
String key = entry.getKey().toString();
|
||||
String value = entry.getValue().toString();
|
||||
if (value.trim().startsWith("${") && value.trim().endsWith("}")) {
|
||||
int beginIndex = value.indexOf(":");
|
||||
if (beginIndex < 0) {
|
||||
beginIndex = value.length() - 1;
|
||||
}
|
||||
int endIndex = value.length() - 1;
|
||||
String envKey = value.substring(2, beginIndex);
|
||||
String envValue = System.getenv(envKey);
|
||||
if (envValue == null || "".equals(envValue.trim())) {
|
||||
value = value.substring(beginIndex + 1, endIndex);
|
||||
} else {
|
||||
value = envValue;
|
||||
}
|
||||
properties.setProperty(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
//
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
class PooledOfficeManager implements OfficeManager {
|
||||
|
||||
private final PooledOfficeManagerSettings settings;
|
||||
private final ManagedOfficeProcess managedOfficeProcess;
|
||||
private final SuspendableThreadPoolExecutor taskExecutor;
|
||||
|
||||
private volatile boolean stopping = false;
|
||||
private int taskCount;
|
||||
private Future<?> currentTask;
|
||||
|
||||
private final Logger logger = Logger.getLogger(getClass().getName());
|
||||
|
||||
private OfficeConnectionEventListener connectionEventListener = new OfficeConnectionEventListener() {
|
||||
public void connected(OfficeConnectionEvent event) {
|
||||
taskCount = 0;
|
||||
taskExecutor.setAvailable(true);
|
||||
}
|
||||
public void disconnected(OfficeConnectionEvent event) {
|
||||
taskExecutor.setAvailable(false);
|
||||
if (stopping) {
|
||||
// expected
|
||||
stopping = false;
|
||||
} else {
|
||||
logger.warning("connection lost unexpectedly; attempting restart");
|
||||
if (currentTask != null) {
|
||||
currentTask.cancel(true);
|
||||
}
|
||||
managedOfficeProcess.restartDueToLostConnection();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public PooledOfficeManager(UnoUrl unoUrl) {
|
||||
this(new PooledOfficeManagerSettings(unoUrl));
|
||||
}
|
||||
|
||||
public PooledOfficeManager(PooledOfficeManagerSettings settings) {
|
||||
this.settings = settings;
|
||||
managedOfficeProcess = new ManagedOfficeProcess(settings);
|
||||
managedOfficeProcess.getConnection().addConnectionEventListener(connectionEventListener);
|
||||
taskExecutor = new SuspendableThreadPoolExecutor(new NamedThreadFactory("OfficeTaskThread"));
|
||||
}
|
||||
|
||||
public void execute(final OfficeTask task) throws OfficeException {
|
||||
Future<?> futureTask = taskExecutor.submit(new Runnable() {
|
||||
public void run() {
|
||||
if (settings.getMaxTasksPerProcess() > 0 && ++taskCount == settings.getMaxTasksPerProcess() + 1) {
|
||||
logger.info(String.format("reached limit of %d maxTasksPerProcess: restarting", settings.getMaxTasksPerProcess()));
|
||||
taskExecutor.setAvailable(false);
|
||||
stopping = true;
|
||||
managedOfficeProcess.restartAndWait();
|
||||
//FIXME taskCount will be 0 rather than 1 at this point
|
||||
}
|
||||
task.execute(managedOfficeProcess.getConnection());
|
||||
}
|
||||
});
|
||||
currentTask = futureTask;
|
||||
try {
|
||||
futureTask.get(settings.getTaskExecutionTimeout(), TimeUnit.MILLISECONDS);
|
||||
} catch (TimeoutException timeoutException) {
|
||||
managedOfficeProcess.restartDueToTaskTimeout();
|
||||
throw new OfficeException("task did not complete within timeout", timeoutException);
|
||||
} catch (ExecutionException executionException) {
|
||||
if (executionException.getCause() instanceof OfficeException) {
|
||||
throw (OfficeException) executionException.getCause();
|
||||
} else {
|
||||
throw new OfficeException("task failed", executionException.getCause());
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
throw new OfficeException("task failed", exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void start() throws OfficeException {
|
||||
managedOfficeProcess.startAndWait();
|
||||
}
|
||||
|
||||
public void stop() throws OfficeException {
|
||||
taskExecutor.setAvailable(false);
|
||||
stopping = true;
|
||||
taskExecutor.shutdownNow();
|
||||
managedOfficeProcess.stopAndWait();
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return managedOfficeProcess.isConnected();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
class PooledOfficeManagerSettings extends ManagedOfficeProcessSettings {
|
||||
|
||||
public static final long DEFAULT_TASK_EXECUTION_TIMEOUT = 120000L;
|
||||
public static final int DEFAULT_MAX_TASKS_PER_PROCESS = 200;
|
||||
|
||||
private long taskExecutionTimeout = DEFAULT_TASK_EXECUTION_TIMEOUT;
|
||||
private int maxTasksPerProcess = DEFAULT_MAX_TASKS_PER_PROCESS;
|
||||
|
||||
public PooledOfficeManagerSettings(UnoUrl unoUrl) {
|
||||
super(unoUrl);
|
||||
}
|
||||
|
||||
public long getTaskExecutionTimeout() {
|
||||
return taskExecutionTimeout;
|
||||
}
|
||||
|
||||
public void setTaskExecutionTimeout(long taskExecutionTimeout) {
|
||||
this.taskExecutionTimeout = taskExecutionTimeout;
|
||||
}
|
||||
|
||||
public int getMaxTasksPerProcess() {
|
||||
return maxTasksPerProcess;
|
||||
}
|
||||
|
||||
public void setMaxTasksPerProcess(int maxTasksPerProcess) {
|
||||
this.maxTasksPerProcess = maxTasksPerProcess;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.artofsolving.jodconverter.process.ProcessManager;
|
||||
|
||||
class ProcessPoolOfficeManager implements OfficeManager {
|
||||
|
||||
private final BlockingQueue<PooledOfficeManager> pool;
|
||||
private final PooledOfficeManager[] pooledManagers;
|
||||
private final long taskQueueTimeout;
|
||||
|
||||
private volatile boolean running = false;
|
||||
|
||||
private final Logger logger = Logger.getLogger(ProcessPoolOfficeManager.class.getName());
|
||||
|
||||
public ProcessPoolOfficeManager(File officeHome, UnoUrl[] unoUrls, String[] runAsArgs, File templateProfileDir, File workDir,
|
||||
long retryTimeout, long taskQueueTimeout, long taskExecutionTimeout, int maxTasksPerProcess,
|
||||
ProcessManager processManager) {
|
||||
this.taskQueueTimeout = taskQueueTimeout;
|
||||
pool = new ArrayBlockingQueue<PooledOfficeManager>(unoUrls.length);
|
||||
pooledManagers = new PooledOfficeManager[unoUrls.length];
|
||||
for (int i = 0; i < unoUrls.length; i++) {
|
||||
PooledOfficeManagerSettings settings = new PooledOfficeManagerSettings(unoUrls[i]);
|
||||
settings.setRunAsArgs(runAsArgs);
|
||||
settings.setTemplateProfileDir(templateProfileDir);
|
||||
settings.setWorkDir(workDir);
|
||||
settings.setOfficeHome(officeHome);
|
||||
settings.setRetryTimeout(retryTimeout);
|
||||
settings.setTaskExecutionTimeout(taskExecutionTimeout);
|
||||
settings.setMaxTasksPerProcess(maxTasksPerProcess);
|
||||
settings.setProcessManager(processManager);
|
||||
pooledManagers[i] = new PooledOfficeManager(settings);
|
||||
}
|
||||
logger.info("ProcessManager implementation is " + processManager.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
public synchronized void start() throws OfficeException {
|
||||
for (int i = 0; i < pooledManagers.length; i++) {
|
||||
pooledManagers[i].start();
|
||||
releaseManager(pooledManagers[i]);
|
||||
}
|
||||
running = true;
|
||||
}
|
||||
|
||||
public void execute(OfficeTask task) throws IllegalStateException, OfficeException {
|
||||
if (!running) {
|
||||
throw new IllegalStateException("this OfficeManager is currently stopped");
|
||||
}
|
||||
PooledOfficeManager manager = null;
|
||||
try {
|
||||
manager = acquireManager();
|
||||
if (manager == null) {
|
||||
throw new OfficeException("no office manager available");
|
||||
}
|
||||
manager.execute(task);
|
||||
} finally {
|
||||
if (manager != null) {
|
||||
releaseManager(manager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void stop() throws OfficeException {
|
||||
running = false;
|
||||
logger.info("stopping");
|
||||
pool.clear();
|
||||
for (int i = 0; i < pooledManagers.length; i++) {
|
||||
pooledManagers[i].stop();
|
||||
}
|
||||
logger.info("stopped");
|
||||
}
|
||||
|
||||
private PooledOfficeManager acquireManager() {
|
||||
try {
|
||||
return pool.poll(taskQueueTimeout, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException interruptedException) {
|
||||
throw new OfficeException("interrupted", interruptedException);
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseManager(PooledOfficeManager manager) {
|
||||
try {
|
||||
pool.put(manager);
|
||||
} catch (InterruptedException interruptedException) {
|
||||
throw new OfficeException("interrupted", interruptedException);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
class RetryTimeoutException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -3704437769955257514L;
|
||||
|
||||
public RetryTimeoutException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
abstract class Retryable {
|
||||
|
||||
/**
|
||||
* @throws TemporaryException for an error condition that can be temporary - i.e. retrying later could be successful
|
||||
* @throws Exception for all other error conditions
|
||||
*/
|
||||
protected abstract void attempt() throws TemporaryException, Exception;
|
||||
|
||||
public void execute(long interval, long timeout) throws RetryTimeoutException, Exception {
|
||||
execute(0L, interval, timeout);
|
||||
}
|
||||
|
||||
public void execute(long delay, long interval, long timeout) throws RetryTimeoutException, Exception {
|
||||
long start = System.currentTimeMillis();
|
||||
if (delay > 0L) {
|
||||
sleep(delay);
|
||||
}
|
||||
while (true) {
|
||||
try {
|
||||
attempt();
|
||||
return;
|
||||
} catch (TemporaryException temporaryException) {
|
||||
if (System.currentTimeMillis() - start < timeout) {
|
||||
sleep(interval);
|
||||
// continue
|
||||
} else {
|
||||
throw new RetryTimeoutException(temporaryException.getCause());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sleep(long millis) {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException interruptedException) {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
class SuspendableThreadPoolExecutor extends ThreadPoolExecutor {
|
||||
|
||||
private boolean available = false;
|
||||
private ReentrantLock suspendLock = new ReentrantLock();
|
||||
private Condition availableCondition = suspendLock.newCondition();
|
||||
|
||||
public SuspendableThreadPoolExecutor(ThreadFactory threadFactory) {
|
||||
super(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeExecute(Thread thread, Runnable task) {
|
||||
super.beforeExecute(thread, task);
|
||||
suspendLock.lock();
|
||||
try {
|
||||
while (!available) {
|
||||
availableCondition.await();
|
||||
}
|
||||
} catch (InterruptedException interruptedException) {
|
||||
thread.interrupt();
|
||||
} finally {
|
||||
suspendLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void setAvailable(boolean available) {
|
||||
suspendLock.lock();
|
||||
try {
|
||||
this.available = available;
|
||||
if (available) {
|
||||
availableCondition.signalAll();
|
||||
}
|
||||
} finally {
|
||||
suspendLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* Represents an error condition that can be temporary, i.e. that could go
|
||||
* away by simply retrying the same operation after an interval.
|
||||
*/
|
||||
class TemporaryException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 7237380113208327295L;
|
||||
|
||||
public TemporaryException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(new BigDecimal("7412611111110.99"));
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.office;
|
||||
|
||||
/**
|
||||
* Encapsulates the UNO Interprocess Connection type and parameters.
|
||||
* <p>
|
||||
* OpenOffice.org supports two connection types: TCP sockets and named pipes.
|
||||
* Named pipes are marginally faster and do not take up a TCP port, but they
|
||||
* require native libraries, which means setting <em>java.library.path</em>
|
||||
* when starting Java. E.g. on Linux
|
||||
* <pre>
|
||||
* java -Djava.library.path=/opt/openoffice.org/ure/lib ...
|
||||
* </pre>
|
||||
* <p>
|
||||
* See <a href="http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/ProUNO/Opening_a_Connection">Opening a Connection</a>
|
||||
* in the OpenOffice.org Developer's Guide for more details.
|
||||
*/
|
||||
class UnoUrl {
|
||||
|
||||
private final String acceptString;
|
||||
private final String connectString;
|
||||
|
||||
private UnoUrl(String acceptString, String connectString) {
|
||||
this.acceptString = acceptString;
|
||||
this.connectString = connectString;
|
||||
}
|
||||
|
||||
public static UnoUrl socket(int port) {
|
||||
String socketString = "socket,host=127.0.0.1,port=" + port;
|
||||
return new UnoUrl(socketString, socketString + ",tcpNoDelay=1");
|
||||
}
|
||||
|
||||
public static UnoUrl pipe(String pipeName) {
|
||||
String pipeString = "pipe,name=" + pipeName;
|
||||
return new UnoUrl(pipeString, pipeString);
|
||||
}
|
||||
|
||||
public String getAcceptString() {
|
||||
return acceptString;
|
||||
}
|
||||
|
||||
public String getConnectString() {
|
||||
return connectString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return connectString;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.process;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
/**
|
||||
* {@link ProcessManager} implementation for Linux. Uses the <tt>ps</tt>
|
||||
* and <tt>kill</tt> commands.
|
||||
* <p>
|
||||
* Should Work on Solaris too, except that the command line string
|
||||
* returned by <tt>ps</tt> there is limited to 80 characters and this affects
|
||||
* {@link #findPid(String)}.
|
||||
*/
|
||||
public class LinuxProcessManager implements ProcessManager {
|
||||
|
||||
private static final Pattern PS_OUTPUT_LINE = Pattern.compile("^\\s*(\\d+)\\s+(.*)$");
|
||||
|
||||
private String[] runAsArgs;
|
||||
|
||||
public void setRunAsArgs(String... runAsArgs) {
|
||||
this.runAsArgs = runAsArgs;
|
||||
}
|
||||
|
||||
protected String[] psCommand() {
|
||||
return new String[] { "/bin/ps", "-e", "-o", "pid,args" };
|
||||
}
|
||||
|
||||
public long findPid(ProcessQuery query) throws IOException {
|
||||
String regex = Pattern.quote(query.getCommand()) + ".*" + Pattern.quote(query.getArgument());
|
||||
Pattern commandPattern = Pattern.compile(regex);
|
||||
for (String line : execute(psCommand())) {
|
||||
Matcher lineMatcher = PS_OUTPUT_LINE.matcher(line);
|
||||
if (lineMatcher.matches()) {
|
||||
String command = lineMatcher.group(2);
|
||||
Matcher commandMatcher = commandPattern.matcher(command);
|
||||
if (commandMatcher.find()) {
|
||||
return Long.parseLong(lineMatcher.group(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return PID_NOT_FOUND;
|
||||
}
|
||||
|
||||
public void kill(Process process, long pid) throws IOException {
|
||||
if (pid <= 0) {
|
||||
throw new IllegalArgumentException("invalid pid: " + pid);
|
||||
}
|
||||
execute("/bin/kill", "-KILL", Long.toString(pid));
|
||||
}
|
||||
|
||||
private List<String> execute(String... args) throws IOException {
|
||||
String[] command;
|
||||
if (runAsArgs != null) {
|
||||
command = new String[runAsArgs.length + args.length];
|
||||
System.arraycopy(runAsArgs, 0, command, 0, runAsArgs.length);
|
||||
System.arraycopy(args, 0, command, runAsArgs.length, args.length);
|
||||
} else {
|
||||
command = args;
|
||||
}
|
||||
Process process = new ProcessBuilder(command).start();
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> lines = IOUtils.readLines(process.getInputStream());
|
||||
return lines;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.process;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface ProcessManager {
|
||||
|
||||
public static final long PID_NOT_FOUND = -2;
|
||||
public static final long PID_UNKNOWN = -1;
|
||||
|
||||
void kill(Process process, long pid) throws IOException;
|
||||
|
||||
/**
|
||||
* @param query
|
||||
* @return the pid if found, {@link #PID_NOT_FOUND} if not,
|
||||
* or {@link #PID_UNKNOWN} if this implementation is unable to find out
|
||||
* @throws IOException
|
||||
*/
|
||||
long findPid(ProcessQuery query) throws IOException;
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.process;
|
||||
|
||||
public class ProcessQuery {
|
||||
|
||||
private final String command;
|
||||
private final String argument;
|
||||
|
||||
public ProcessQuery(String command, String argument) {
|
||||
this.command = command;
|
||||
this.argument = argument;
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public String getArgument() {
|
||||
return argument;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.process;
|
||||
|
||||
public class PureJavaProcessManager implements ProcessManager {
|
||||
|
||||
public long findPid(ProcessQuery query) {
|
||||
return PID_UNKNOWN;
|
||||
}
|
||||
|
||||
public void kill(Process process, long pid) {
|
||||
process.destroy();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.process;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.hyperic.sigar.Sigar;
|
||||
import org.hyperic.sigar.SigarException;
|
||||
import org.hyperic.sigar.ptql.ProcessFinder;
|
||||
|
||||
/**
|
||||
* {@link ProcessManager} implementation that uses the SIGAR library.
|
||||
* <p>
|
||||
* Requires the sigar.jar in the classpath and the appropriate system-specific
|
||||
* native library (e.g. <tt>libsigar-x86-linux.so</tt> on Linux x86) available
|
||||
* in the <em>java.library.path</em>.
|
||||
* <p>
|
||||
* See the <a href="http://support.hyperic.com/display/SIGAR">SIGAR site</a>
|
||||
* for documentation and downloads.
|
||||
*/
|
||||
public class SigarProcessManager implements ProcessManager {
|
||||
|
||||
public long findPid(ProcessQuery query) throws IOException {
|
||||
Sigar sigar = new Sigar();
|
||||
try {
|
||||
long[] pids = ProcessFinder.find(sigar, "State.Name.eq=" + query.getCommand());
|
||||
for (int i = 0; i < pids.length; i++) {
|
||||
String[] arguments = sigar.getProcArgs(pids[i]);
|
||||
if (arguments != null && argumentMatches(arguments, query.getArgument())) {
|
||||
return pids[i];
|
||||
}
|
||||
}
|
||||
return PID_NOT_FOUND;
|
||||
} catch (SigarException sigarException) {
|
||||
throw new IOException("findPid failed", sigarException);
|
||||
} finally {
|
||||
sigar.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void kill(Process process, long pid) throws IOException {
|
||||
Sigar sigar = new Sigar();
|
||||
try {
|
||||
sigar.kill(pid, Sigar.getSigNum("KILL"));
|
||||
} catch (SigarException sigarException) {
|
||||
throw new IOException("kill failed", sigarException);
|
||||
} finally {
|
||||
sigar.close();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean argumentMatches(String[] arguments, String expected) {
|
||||
for (String argument : arguments) {
|
||||
if (argument.contains(expected)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
//
|
||||
// JODConverter - Java OpenDocument Converter
|
||||
// Copyright 2004-2012 Mirko Nasato and contributors
|
||||
//
|
||||
// JODConverter is Open Source software, you can redistribute it and/or
|
||||
// modify it under either (at your option) of the following licenses
|
||||
//
|
||||
// 1. The GNU Lesser General Public License v3 (or later)
|
||||
// -> http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// 2. The Apache License, Version 2.0
|
||||
// -> http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
//
|
||||
package org.artofsolving.jodconverter.util;
|
||||
|
||||
public class PlatformUtils {
|
||||
|
||||
private static final String OS_NAME = System.getProperty("os.name").toLowerCase();
|
||||
|
||||
private PlatformUtils() {
|
||||
throw new AssertionError("utility class must not be instantiated");
|
||||
}
|
||||
|
||||
public static boolean isLinux() {
|
||||
return OS_NAME.startsWith("linux");
|
||||
}
|
||||
|
||||
public static boolean isMac() {
|
||||
return OS_NAME.startsWith("mac");
|
||||
}
|
||||
|
||||
public static boolean isWindows() {
|
||||
return OS_NAME.startsWith("windows");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,188 @@
|
||||
[
|
||||
{
|
||||
"name": "Portable Document Format",
|
||||
"extension": "pdf",
|
||||
"mediaType": "application/pdf",
|
||||
"storePropertiesByFamily": {
|
||||
"DRAWING": {"FilterName": "draw_pdf_Export"},
|
||||
"SPREADSHEET": {"FilterName": "calc_pdf_Export"},
|
||||
"PRESENTATION": {"FilterName": "impress_pdf_Export"},
|
||||
"TEXT": {"FilterName": "writer_pdf_Export"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Macromedia Flash",
|
||||
"extension": "swf",
|
||||
"mediaType": "application/x-shockwave-flash",
|
||||
"storePropertiesByFamily": {
|
||||
"DRAWING": {"FilterName": "draw_flash_Export"},
|
||||
"PRESENTATION": {"FilterName": "impress_flash_Export"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "HTML",
|
||||
"extension": "html",
|
||||
"mediaType": "text/html",
|
||||
"inputFamily": "TEXT",
|
||||
"storePropertiesByFamily": {
|
||||
"SPREADSHEET": {"FilterName": "HTML (StarCalc)"},
|
||||
"PRESENTATION": {"FilterName": "impress_html_Export"},
|
||||
"TEXT": {"FilterName": "HTML (StarWriter)"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "OpenDocument Text",
|
||||
"extension": "odt",
|
||||
"mediaType": "application/vnd.oasis.opendocument.text",
|
||||
"inputFamily": "TEXT",
|
||||
"storePropertiesByFamily": {"TEXT": {"FilterName": "writer8"}}
|
||||
},
|
||||
{
|
||||
"name": "OpenOffice.org 1.0 Text Document",
|
||||
"extension": "sxw",
|
||||
"mediaType": "application/vnd.sun.xml.writer",
|
||||
"inputFamily": "TEXT",
|
||||
"storePropertiesByFamily": {"TEXT": {"FilterName": "StarOffice XML (Writer)"}}
|
||||
},
|
||||
{
|
||||
"name": "Microsoft Word",
|
||||
"extension": "doc",
|
||||
"mediaType": "application/msword",
|
||||
"inputFamily": "TEXT",
|
||||
"storePropertiesByFamily": {"TEXT": {"FilterName": "MS Word 97"}}
|
||||
},
|
||||
{
|
||||
"name": "Microsoft Word 2007 XML",
|
||||
"extension": "docx",
|
||||
"mediaType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
"inputFamily": "TEXT"
|
||||
},
|
||||
{
|
||||
"name": "Rich Text Format",
|
||||
"extension": "rtf",
|
||||
"mediaType": "text/rtf",
|
||||
"inputFamily": "TEXT",
|
||||
"storePropertiesByFamily": {"TEXT": {"FilterName": "Rich Text Format"}}
|
||||
},
|
||||
{
|
||||
"name": "WordPerfect",
|
||||
"extension": "wpd",
|
||||
"mediaType": "application/wordperfect",
|
||||
"inputFamily": "TEXT"
|
||||
},
|
||||
{
|
||||
"name": "Plain Text",
|
||||
"extension": "txt",
|
||||
"mediaType": "text/plain",
|
||||
"inputFamily": "TEXT",
|
||||
"loadProperties": {
|
||||
"FilterName": "Text (encoded)",
|
||||
"FilterOptions": "utf8"
|
||||
},
|
||||
"storePropertiesByFamily": {"TEXT": {
|
||||
"FilterName": "Text (encoded)",
|
||||
"FilterOptions": "utf8"
|
||||
}}
|
||||
},
|
||||
{
|
||||
"name": "MediaWiki wikitext",
|
||||
"extension": "wiki",
|
||||
"mediaType": "text/x-wiki",
|
||||
"storePropertiesByFamily": {"TEXT": {"FilterName": "MediaWiki"}}
|
||||
},
|
||||
{
|
||||
"name": "OpenDocument Spreadsheet",
|
||||
"extension": "ods",
|
||||
"mediaType": "application/vnd.oasis.opendocument.spreadsheet",
|
||||
"inputFamily": "SPREADSHEET",
|
||||
"storePropertiesByFamily": {"SPREADSHEET": {"FilterName": "calc8"}}
|
||||
},
|
||||
{
|
||||
"name": "OpenOffice.org 1.0 Spreadsheet",
|
||||
"extension": "sxc",
|
||||
"mediaType": "application/vnd.sun.xml.calc",
|
||||
"inputFamily": "SPREADSHEET",
|
||||
"storePropertiesByFamily": {"SPREADSHEET": {"FilterName": "StarOffice XML (Calc)"}}
|
||||
},
|
||||
{
|
||||
"name": "Microsoft Excel",
|
||||
"extension": "xls",
|
||||
"mediaType": "application/vnd.ms-excel",
|
||||
"inputFamily": "SPREADSHEET",
|
||||
"storePropertiesByFamily": {"SPREADSHEET": {"FilterName": "MS Excel 97"}}
|
||||
},
|
||||
{
|
||||
"name": "Microsoft Excel 2007 XML",
|
||||
"extension": "xlsx",
|
||||
"mediaType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
"inputFamily": "SPREADSHEET"
|
||||
},
|
||||
{
|
||||
"name": "Comma Separated Values",
|
||||
"extension": "csv",
|
||||
"mediaType": "text/csv",
|
||||
"inputFamily": "SPREADSHEET",
|
||||
"loadProperties": {
|
||||
"FilterName": "Text - txt - csv (StarCalc)",
|
||||
"FilterOptions": "44,34,0"
|
||||
},
|
||||
"storePropertiesByFamily": {"SPREADSHEET": {
|
||||
"FilterName": "Text - txt - csv (StarCalc)",
|
||||
"FilterOptions": "44,34,0"
|
||||
}}
|
||||
},
|
||||
{
|
||||
"name": "Tab Separated Values",
|
||||
"extension": "tsv",
|
||||
"mediaType": "text/tab-separated-values",
|
||||
"inputFamily": "SPREADSHEET",
|
||||
"loadProperties": {
|
||||
"FilterName": "Text - txt - csv (StarCalc)",
|
||||
"FilterOptions": "9,34,0"
|
||||
},
|
||||
"storePropertiesByFamily": {"SPREADSHEET": {
|
||||
"FilterName": "Text - txt - csv (StarCalc)",
|
||||
"FilterOptions": "9,34,0"
|
||||
}}
|
||||
},
|
||||
{
|
||||
"name": "OpenDocument Presentation",
|
||||
"extension": "odp",
|
||||
"mediaType": "application/vnd.oasis.opendocument.presentation",
|
||||
"inputFamily": "PRESENTATION",
|
||||
"storePropertiesByFamily": {"PRESENTATION": {"FilterName": "impress8"}}
|
||||
},
|
||||
{
|
||||
"name": "OpenOffice.org 1.0 Presentation",
|
||||
"extension": "sxi",
|
||||
"mediaType": "application/vnd.sun.xml.impress",
|
||||
"inputFamily": "PRESENTATION",
|
||||
"storePropertiesByFamily": {"PRESENTATION": {"FilterName": "StarOffice XML (Impress)"}}
|
||||
},
|
||||
{
|
||||
"name": "Microsoft PowerPoint",
|
||||
"extension": "ppt",
|
||||
"mediaType": "application/vnd.ms-powerpoint",
|
||||
"inputFamily": "PRESENTATION",
|
||||
"storePropertiesByFamily": {"PRESENTATION": {"FilterName": "MS PowerPoint 97"}}
|
||||
},
|
||||
{
|
||||
"name": "Microsoft PowerPoint 2007 XML",
|
||||
"extension": "pptx",
|
||||
"mediaType": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||
"inputFamily": "PRESENTATION"
|
||||
},
|
||||
{
|
||||
"name": "OpenDocument Drawing",
|
||||
"extension": "odg",
|
||||
"mediaType": "application/vnd.oasis.opendocument.graphics",
|
||||
"inputFamily": "DRAWING",
|
||||
"storePropertiesByFamily": {"DRAWING": {"FilterName": "draw8"}}
|
||||
},
|
||||
{
|
||||
"name": "Scalable Vector Graphics",
|
||||
"extension": "svg",
|
||||
"mediaType": "image/svg+xml",
|
||||
"storePropertiesByFamily": {"DRAWING": {"FilterName": "draw_svg_Export"}}
|
||||
}
|
||||
]
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,63 @@
|
||||
C:\Users\lyf\Documents\fileview\file-online-preview\jodconverter-web\target
|
||||
|
||||
. ____ _ __ _ _
|
||||
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
|
||||
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
|
||||
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
|
||||
' |____| .__|_| |_|_| |_\__, | / / / /
|
||||
=========|_|==============|___/=/_/_/_/
|
||||
:: Spring Boot :: (v2.2.2.RELEASE)
|
||||
|
||||
2020-03-31 17:21:06.323 INFO 14272 --- [ main] cn.keking.FilePreviewApplication : Starting FilePreviewApplication v2.2.0-SNAPSHOT on DESKTOP-RKVHFJ0 with PID 14272 (C:\Users\lyf\Documents\fileview\file-online-preview\jodconverter-web\target\kkFileView-2.2.0-SNAPSHOT.jar started by lyf in C:\Users\lyf\Documents\fileview\file-online-preview\jodconverter-web\target)
|
||||
2020-03-31 17:21:06.326 INFO 14272 --- [ main] cn.keking.FilePreviewApplication : No active profile set, falling back to default profiles: default
|
||||
2020-03-31 17:21:07.524 INFO 14272 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8012 (http)
|
||||
2020-03-31 17:21:07.535 INFO 14272 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||
2020-03-31 17:21:07.535 INFO 14272 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.29]
|
||||
2020-03-31 17:21:07.602 INFO 14272 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||
2020-03-31 17:21:07.602 INFO 14272 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1236 ms
|
||||
2020-03-31 17:21:07.649 WARN 14272 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'converterUtils': Invocation of init method failed; nested exception is java.lang.NullPointerException
|
||||
2020-03-31 17:21:07.651 INFO 14272 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
|
||||
2020-03-31 17:21:07.660 INFO 14272 --- [ main] ConditionEvaluationReportLoggingListener :
|
||||
|
||||
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
|
||||
2020-03-31 17:21:07.663 ERROR 14272 --- [ main] o.s.boot.SpringApplication : Application run failed
|
||||
|
||||
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'converterUtils': Invocation of init method failed; nested exception is java.lang.NullPointerException
|
||||
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:160) ~[spring-beans-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:416) ~[spring-beans-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788) ~[spring-beans-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879) ~[spring-beans-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) ~[spring-context-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
|
||||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
|
||||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
|
||||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
|
||||
at cn.keking.FilePreviewApplication.main(FilePreviewApplication.java:16) [classes!/:2.2.0-SNAPSHOT]
|
||||
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_212]
|
||||
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_212]
|
||||
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_212]
|
||||
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_212]
|
||||
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) [kkFileView-2.2.0-SNAPSHOT.jar:2.2.0-SNAPSHOT]
|
||||
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) [kkFileView-2.2.0-SNAPSHOT.jar:2.2.0-SNAPSHOT]
|
||||
at org.springframework.boot.loader.Launcher.launch(Launcher.java:51) [kkFileView-2.2.0-SNAPSHOT.jar:2.2.0-SNAPSHOT]
|
||||
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:52) [kkFileView-2.2.0-SNAPSHOT.jar:2.2.0-SNAPSHOT]
|
||||
Caused by: java.lang.NullPointerException: null
|
||||
at cn.keking.utils.ConverterUtils.initOfficeManager(ConverterUtils.java:43) ~[classes!/:2.2.0-SNAPSHOT]
|
||||
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_212]
|
||||
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_212]
|
||||
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_212]
|
||||
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_212]
|
||||
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389) ~[spring-beans-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) ~[spring-beans-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) ~[spring-beans-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
|
||||
... 26 common frames omitted
|
||||
|
@ -0,0 +1,54 @@
|
||||
<!--***********************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***********************************************************-->
|
||||
<xsl:stylesheet version="1.0" encoding="UTF-8"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:office="http://openoffice.org/2000/office"
|
||||
xmlns:style="http://openoffice.org/2000/style"
|
||||
xmlns:table="http://openoffice.org/2000/table"
|
||||
xmlns:draw="http://openoffice.org/2000/drawing"
|
||||
xmlns:fo="http://www.w3.org/1999/XSL/Format"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:meta="http://openoffice.org/2000/meta"
|
||||
xmlns:number="http://openoffice.org/2000/datastyle"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:chart="http://openoffice.org/2000/chart"
|
||||
xmlns:help="http://openoffice.org/2000/help"
|
||||
xmlns:index="http://sun.com/2000/XMLSearch"
|
||||
xmlns:text="http://openoffice.org/2000/text">
|
||||
|
||||
<xsl:param name="Language" select="'en-US'"/>
|
||||
<xsl:output method="text" encoding="UTF-8"/>
|
||||
|
||||
<xsl:template match="/">
|
||||
<xsl:apply-templates select="//title" mode="include"/>
|
||||
<xsl:apply-templates select="//paragraph[@role='heading']" mode="include"/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="*" mode="include">
|
||||
<xsl:value-of select="."/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="*"/>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
@ -0,0 +1,124 @@
|
||||
<!--***********************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***********************************************************-->
|
||||
<xsl:stylesheet version="1.0" encoding="UTF-8"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:office="http://openoffice.org/2000/office"
|
||||
xmlns:style="http://openoffice.org/2000/style"
|
||||
xmlns:table="http://openoffice.org/2000/table"
|
||||
xmlns:draw="http://openoffice.org/2000/drawing"
|
||||
xmlns:fo="http://www.w3.org/1999/XSL/Format"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:meta="http://openoffice.org/2000/meta"
|
||||
xmlns:number="http://openoffice.org/2000/datastyle"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:chart="http://openoffice.org/2000/chart"
|
||||
xmlns:help="http://openoffice.org/2000/help"
|
||||
xmlns:index="http://sun.com/2000/XMLSearch"
|
||||
xmlns:text="http://openoffice.org/2000/text">
|
||||
|
||||
<xsl:param name="Language" select="'en-US'"/>
|
||||
<xsl:output method="text" encoding="UTF-8"/>
|
||||
|
||||
<xsl:template match="helpdocument|body">
|
||||
<xsl:choose>
|
||||
<xsl:when test="meta/topic[@indexer='exclude']"/>
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="title">
|
||||
<xsl:value-of select="."/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="table">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="tablecell">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="tablerow">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="list">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="listitem">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="item">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="emph">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="paragraph">
|
||||
<xsl:value-of select="."/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="section">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="bookmark">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="bookmark_value">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="link">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="ahelp[@visibility='visible']">
|
||||
<xsl:value-of select="."/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="*"/>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
||||
|
@ -0,0 +1,960 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
<!--***********************************************************************
|
||||
This is the main transformation style sheet for transforming.
|
||||
Only use with OOo 2.0
|
||||
Owner: fpe@openoffice.org
|
||||
=========================================================================
|
||||
Changes Log
|
||||
May 24 2004 Created
|
||||
Aug 24 2004 Fixed for help2 CWS
|
||||
Aug 27 2004 Added css link, fixed missing embed-mode for variable
|
||||
Removed width/height for images
|
||||
Sep 03 2004 Modularized xsl, added some embedded modes
|
||||
Oct 08 2004 Fixed bug wrong mode "embedded" for links
|
||||
Added embedded modes for embed and embedvar (for cascaded embeds)
|
||||
Added <p> tags around falsely embedded pars and vars
|
||||
Dec 08 2004 #i38483#, fixed wrong handling of web links
|
||||
#i37377#, fixed missing usage of Database parameter for switching
|
||||
Jan 04 2005 #i38905#, fixed buggy branding replacement template
|
||||
Mar 17 2005 #i43972#, added language info to image URL, evaluate Language parameter
|
||||
evaluate new localize attribute in images
|
||||
May 10 2005 #i48785#, fixed wrong setting of distrib variable
|
||||
Aug 16 2005 workaround for #i53365#
|
||||
Aug 19 2005 fixed missing list processing in embedded sections
|
||||
Aug 19 2005 #i53535#, fixed wrong handling of Database parameter
|
||||
Oct 17 2006 #i70462#, disabled sorting to avoid output of error messages to console
|
||||
Jun 15 2009 #i101799#, fixed wrong handling of http URLs with anchors
|
||||
***********************************************************************//-->
|
||||
|
||||
<!--***********************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***********************************************************-->
|
||||
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
|
||||
<xsl:output indent="yes" method="html"/>
|
||||
|
||||
<!--
|
||||
############################
|
||||
# Variables and Parameters #
|
||||
############################
|
||||
//-->
|
||||
|
||||
<!-- General Usage -->
|
||||
<xsl:variable name="am" select="'&'"/>
|
||||
<xsl:variable name="sl" select="'/'"/>
|
||||
<xsl:variable name="qt" select="'"'"/>
|
||||
|
||||
<!-- generic Icon alt text -->
|
||||
<xsl:variable name="alttext" select="'text/shared/00/icon_alt.xhp'"/>
|
||||
|
||||
<!-- For calculating pixel sizes -->
|
||||
<xsl:variable name="dpi" select="'96'"/>
|
||||
<xsl:variable name="dpcm" select="'38'"/>
|
||||
|
||||
<!-- Product brand variables used in the help files -->
|
||||
<xsl:variable name="brand1" select="'$[officename]'"/>
|
||||
<xsl:variable name="brand2" select="'$[officeversion]'"/>
|
||||
<xsl:variable name="brand3" select="'%PRODUCTNAME'"/>
|
||||
<xsl:variable name="brand4" select="'%PRODUCTVERSION'"/>
|
||||
|
||||
<!-- meta data variables from the help file -->
|
||||
<xsl:variable name="filename" select="/helpdocument/meta/topic/filename"/>
|
||||
<xsl:variable name="topic_id" select="/helpdocument/meta/topic/@id"/>
|
||||
<xsl:variable name="topic_status" select="/helpdocument/meta/topic/@status"/>
|
||||
<xsl:variable name="title" select="/helpdocument/meta/topic/title"/>
|
||||
<xsl:variable name="doclang" select="/helpdocument/meta/topic/title/@xml-lang"/>
|
||||
|
||||
<!-- Module and the corresponding switching values-->
|
||||
<xsl:param name="Database" select="'swriter'"/>
|
||||
<xsl:variable name="module" select="$Database"/>
|
||||
<xsl:variable name="appl">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$module = 'swriter'"><xsl:value-of select="'WRITER'"/></xsl:when>
|
||||
<xsl:when test="$module = 'scalc'"><xsl:value-of select="'CALC'"/></xsl:when>
|
||||
<xsl:when test="$module = 'sdraw'"><xsl:value-of select="'DRAW'"/></xsl:when>
|
||||
<xsl:when test="$module = 'simpress'"><xsl:value-of select="'IMPRESS'"/></xsl:when>
|
||||
<xsl:when test="$module = 'schart'"><xsl:value-of select="'CHART'"/></xsl:when>
|
||||
<xsl:when test="$module = 'sbasic'"><xsl:value-of select="'BASIC'"/></xsl:when>
|
||||
<xsl:when test="$module = 'smath'"><xsl:value-of select="'MATH'"/></xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
|
||||
<!-- the other parameters given by the help caller -->
|
||||
<xsl:param name="System" select="'WIN'"/>
|
||||
<xsl:param name="productname" select="'Office'"/>
|
||||
<xsl:param name="productversion" select="''"/>
|
||||
<xsl:variable name="pversion">
|
||||
<xsl:value-of select="translate($productversion,' ','')"/>
|
||||
</xsl:variable>
|
||||
<!-- this is were the images are -->
|
||||
<xsl:param name="imgrepos" select="''"/>
|
||||
<xsl:param name="Id" />
|
||||
<!-- (lame) distinction between OS and Commercial -->
|
||||
<xsl:param name="distrib">
|
||||
<xsl:choose>
|
||||
<xsl:when test="starts-with($productname,'OpenOffice')">
|
||||
<xsl:value-of select="'OpenSource'"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="'COMMERCIAL'"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:param>
|
||||
<xsl:param name="Language" select="'en-US'"/>
|
||||
<xsl:variable name="lang" select="$Language"/>
|
||||
|
||||
<xsl:param name="ExtensionId" select="''"/>
|
||||
<xsl:param name="ExtensionPath" select="''"/>
|
||||
|
||||
|
||||
<!-- parts of help and image urls -->
|
||||
<xsl:variable name="help_url_prefix" select="'vnd.sun.star.help://'"/>
|
||||
<xsl:variable name="img_url_prefix" select="concat('vnd.sun.star.zip://',$imgrepos,'/')"/>
|
||||
<xsl:variable name="urlpost" select="concat('?Language=',$lang,$am,'System=',$System,$am,'UseDB=no')"/>
|
||||
<xsl:variable name="urlpre" select="$help_url_prefix" />
|
||||
<xsl:variable name="linkprefix" select="$urlpre"/>
|
||||
<xsl:variable name="linkpostfix" select="$urlpost"/>
|
||||
|
||||
<xsl:variable name="css" select="'default.css'"/>
|
||||
|
||||
<!-- images for notes, tips and warnings -->
|
||||
<xsl:variable name="note_img" select="concat($img_url_prefix,'res/helpimg/note.png')"/>
|
||||
<xsl:variable name="tip_img" select="concat($img_url_prefix,'res/helpimg/tip.png')"/>
|
||||
<xsl:variable name="warning_img" select="concat($img_url_prefix,'res/helpimg/warning.png')"/>
|
||||
|
||||
<!--
|
||||
#############
|
||||
# Templates #
|
||||
#############
|
||||
//-->
|
||||
|
||||
<!-- Create the document skeleton -->
|
||||
<xsl:template match="/">
|
||||
<xsl:variable name="csslink" select="concat($urlpre,'/',$urlpost)"/>
|
||||
<html>
|
||||
<head>
|
||||
<title><xsl:value-of select="$title"/></title>
|
||||
<link href="{$csslink}" rel="Stylesheet" type="text/css" /> <!-- stylesheet link -->
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
||||
</head>
|
||||
<body lang="{$lang}">
|
||||
<xsl:apply-templates select="/helpdocument/body"/>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<!-- AHELP -->
|
||||
<xsl:template match="ahelp">
|
||||
<xsl:if test="not(@visibility='hidden')"><span class="avis"><xsl:apply-templates /></span></xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
<!-- ALT -->
|
||||
<xsl:template match="alt"/>
|
||||
|
||||
<!-- BOOKMARK -->
|
||||
<xsl:template match="bookmark">
|
||||
<a name="{@id}"></a>
|
||||
<xsl:choose>
|
||||
<xsl:when test="starts-with(@branch,'hid')" />
|
||||
<xsl:otherwise><xsl:apply-templates /></xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
<xsl:template match="bookmark" mode="embedded" />
|
||||
|
||||
<!-- BOOKMARK_VALUE -->
|
||||
<xsl:template match="bookmark_value" />
|
||||
|
||||
<!-- BR -->
|
||||
<xsl:template match="br"><br /></xsl:template>
|
||||
|
||||
<!-- CAPTION -->
|
||||
<xsl:template match="caption" />
|
||||
|
||||
<!-- CASE -->
|
||||
<xsl:template match="case"><xsl:call-template name="insertcase" /></xsl:template>
|
||||
<xsl:template match="case" mode="embedded">
|
||||
<xsl:call-template name="insertcase">
|
||||
<xsl:with-param name="embedded" select="'yes'"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- CASEINLINE -->
|
||||
<xsl:template match="caseinline"><xsl:call-template name="insertcase" /></xsl:template>
|
||||
<xsl:template match="caseinline" mode="embedded">
|
||||
<xsl:call-template name="insertcase">
|
||||
<xsl:with-param name="embedded" select="'yes'"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- COMMENT -->
|
||||
<xsl:template match="comment" />
|
||||
<xsl:template match="comment" mode="embedded"/>
|
||||
|
||||
<!-- CREATED -->
|
||||
<xsl:template match="created" />
|
||||
|
||||
<!-- DEFAULT -->
|
||||
<xsl:template match="default"><xsl:call-template name="insertdefault" /></xsl:template>
|
||||
<xsl:template match="default" mode="embedded">
|
||||
<xsl:call-template name="insertdefault">
|
||||
<xsl:with-param name="embedded" select="'yes'"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- DEFAULTINLINE -->
|
||||
<xsl:template match="defaultinline"><xsl:call-template name="insertdefault" /></xsl:template>
|
||||
<xsl:template match="defaultinline" mode="embedded">
|
||||
<xsl:call-template name="insertdefault">
|
||||
<xsl:with-param name="embedded" select="'yes'"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- EMBED -->
|
||||
<xsl:template match="embed"><xsl:call-template name="resolveembed"/></xsl:template>
|
||||
<xsl:template match="embed" mode="embedded"><xsl:call-template name="resolveembed"/></xsl:template>
|
||||
|
||||
<!-- EMBEDVAR -->
|
||||
<xsl:template match="embedvar"><xsl:call-template name="resolveembedvar"/></xsl:template>
|
||||
<xsl:template match="embedvar" mode="embedded"><xsl:call-template name="resolveembedvar"/></xsl:template>
|
||||
|
||||
<!-- EMPH -->
|
||||
<xsl:template match="emph">
|
||||
<span class="emph"><xsl:apply-templates /></span>
|
||||
</xsl:template>
|
||||
<xsl:template match="emph" mode="embedded">
|
||||
<span class="emph"><xsl:apply-templates /></span>
|
||||
</xsl:template>
|
||||
|
||||
<!-- FILENAME -->
|
||||
<xsl:template match="filename" />
|
||||
|
||||
<!-- HISTORY -->
|
||||
<xsl:template match="history" />
|
||||
|
||||
<!-- IMAGE -->
|
||||
<xsl:template match="image"><xsl:call-template name="insertimage"/></xsl:template>
|
||||
<xsl:template match="image" mode="embedded"><xsl:call-template name="insertimage"/></xsl:template>
|
||||
|
||||
<!-- ITEM -->
|
||||
<xsl:template match="item"><span class="{@type}"><xsl:apply-templates /></span></xsl:template>
|
||||
<xsl:template match="item" mode="embedded"><span class="{@type}"><xsl:apply-templates /></span></xsl:template>
|
||||
|
||||
<!-- LASTEDITED -->
|
||||
<xsl:template match="lastedited" />
|
||||
|
||||
<!-- LINK -->
|
||||
<xsl:template match="link">
|
||||
<xsl:choose> <!-- don't insert the heading link to itself -->
|
||||
<xsl:when test="(concat('/',@href) = /helpdocument/meta/topic/filename) or (@href = /helpdocument/meta/topic/filename)">
|
||||
<xsl:apply-templates />
|
||||
</xsl:when>
|
||||
<xsl:when test="contains(child::embedvar/@href,'/00/00000004.xhp#wie')"> <!-- special treatment of howtoget links -->
|
||||
<xsl:call-template name="insert_howtoget">
|
||||
<xsl:with-param name="linkhref" select="@href"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:call-template name="createlink" />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
<xsl:template match="link" mode="embedded">
|
||||
<xsl:call-template name="createlink"/>
|
||||
</xsl:template>
|
||||
|
||||
<!-- LIST -->
|
||||
<xsl:template match="list">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@type='ordered'">
|
||||
<ol>
|
||||
<xsl:if test="@startwith">
|
||||
<xsl:attribute name="start"><xsl:value-of select="@startwith"/></xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates />
|
||||
</ol>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<ul><xsl:apply-templates /></ul>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="list" mode="embedded">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@type='ordered'">
|
||||
<ol>
|
||||
<xsl:if test="@startwith">
|
||||
<xsl:attribute name="start"><xsl:value-of select="@startwith"/></xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates mode="embedded"/>
|
||||
</ol>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<ul><xsl:apply-templates mode="embedded"/></ul>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<!-- LISTITEM -->
|
||||
<xsl:template match="listitem">
|
||||
<li><xsl:apply-templates /></li>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="listitem" mode="embedded">
|
||||
<li><xsl:apply-templates mode="embedded"/></li>
|
||||
</xsl:template>
|
||||
|
||||
<!-- META, SEE HEADER -->
|
||||
<xsl:template match="meta" />
|
||||
|
||||
<!-- OBJECT (UNUSED) -->
|
||||
<xsl:template match="object" />
|
||||
|
||||
<!-- PARAGRAPH -->
|
||||
<xsl:template match="paragraph">
|
||||
<xsl:choose>
|
||||
|
||||
<xsl:when test="@role='heading'">
|
||||
<xsl:call-template name="insertheading">
|
||||
<xsl:with-param name="level" select="@level"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:when test="contains(' note warning tip ',@role)">
|
||||
<xsl:call-template name="insertnote">
|
||||
<xsl:with-param name="type" select="@role" />
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:when test="contains(descendant::embedvar/@href,'/00/00000004.xhp#wie')"> <!-- special treatment of howtoget links -->
|
||||
<xsl:apply-templates />
|
||||
</xsl:when>
|
||||
|
||||
<xsl:otherwise>
|
||||
<xsl:call-template name="insertpara" />
|
||||
</xsl:otherwise>
|
||||
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="paragraph" mode="embedded">
|
||||
<xsl:choose>
|
||||
|
||||
<xsl:when test="@role='heading'"> <!-- increase the level of headings that are embedded -->
|
||||
<!--
|
||||
The internal sablotron processor does not seem to support the number function.
|
||||
Therefore, we need a workaround for
|
||||
<xsl:variable name="level"><xsl:value-of select="number(@level)+1"/></xsl:variable>
|
||||
-->
|
||||
<xsl:variable name="newlevel">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@level='1'"><xsl:value-of select="'2'"/></xsl:when>
|
||||
<xsl:when test="@level='2'"><xsl:value-of select="'2'"/></xsl:when>
|
||||
<xsl:when test="@level='3'"><xsl:value-of select="'3'"/></xsl:when>
|
||||
<xsl:when test="@level='4'"><xsl:value-of select="'4'"/></xsl:when>
|
||||
<xsl:when test="@level='5'"><xsl:value-of select="'5'"/></xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:call-template name="insertheading">
|
||||
<xsl:with-param name="level" select="$newlevel"/>
|
||||
<xsl:with-param name="embedded" select="'yes'"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:when test="contains(' note warning tip ',@role)">
|
||||
<xsl:call-template name="insertnote">
|
||||
<xsl:with-param name="type" select="@role" />
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:when test="contains(descendant::embedvar/@href,'/00/00000004.xhp#wie')"> <!-- special treatment of howtoget links -->
|
||||
<xsl:apply-templates />
|
||||
</xsl:when>
|
||||
|
||||
<xsl:otherwise>
|
||||
<xsl:call-template name="insertpara" />
|
||||
</xsl:otherwise>
|
||||
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- SECTION -->
|
||||
<xsl:template match="section">
|
||||
<a name="{@id}"></a>
|
||||
|
||||
<xsl:choose>
|
||||
|
||||
<xsl:when test="@id='relatedtopics'">
|
||||
<div class="relatedtopics">
|
||||
<xsl:variable name="href"><xsl:value-of select="concat($urlpre,'shared/text/shared/00/00000004.xhp',$urlpost)"/></xsl:variable>
|
||||
<xsl:variable name="anchor"><xsl:value-of select="'related'"/></xsl:variable>
|
||||
<xsl:variable name="doc" select="document($href)"/>
|
||||
<p class="related">
|
||||
<xsl:apply-templates select="$doc//variable[@id=$anchor]"/>
|
||||
</p>
|
||||
<div class="relatedbody">
|
||||
<xsl:apply-templates />
|
||||
</div>
|
||||
</div>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:when test="@id='howtoget'">
|
||||
<xsl:call-template name="insert_howtoget" />
|
||||
</xsl:when>
|
||||
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:otherwise>
|
||||
|
||||
</xsl:choose>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- SECTION -->
|
||||
<xsl:template match="section" mode="embedded">
|
||||
<a name="{@id}"></a>
|
||||
<xsl:apply-templates mode="embedded"/>
|
||||
</xsl:template>
|
||||
|
||||
<!-- SORT -->
|
||||
<xsl:template match="sort" >
|
||||
<xsl:apply-templates><xsl:sort select="descendant::paragraph"/></xsl:apply-templates>
|
||||
</xsl:template>
|
||||
<xsl:template match="sort" mode="embedded">
|
||||
<xsl:apply-templates><xsl:sort select="descendant::paragraph"/></xsl:apply-templates>
|
||||
</xsl:template>
|
||||
|
||||
<!-- SWITCH -->
|
||||
<xsl:template match="switch"><xsl:apply-templates /></xsl:template>
|
||||
<xsl:template match="switch" mode="embedded"><xsl:apply-templates /></xsl:template>
|
||||
|
||||
<!-- SWITCHINLINE -->
|
||||
<xsl:template match="switchinline"><xsl:apply-templates /></xsl:template>
|
||||
<xsl:template match="switchinline" mode="embedded"><xsl:apply-templates mode="embedded"/></xsl:template>
|
||||
|
||||
<!-- TABLE -->
|
||||
<xsl:template match="table"><xsl:call-template name="inserttable"/></xsl:template>
|
||||
<xsl:template match="table" mode="embedded"><xsl:call-template name="inserttable"/></xsl:template>
|
||||
|
||||
<!-- TABLECELL -->
|
||||
<xsl:template match="tablecell"><td valign="top"><xsl:apply-templates /></td></xsl:template>
|
||||
<xsl:template match="tablecell" mode="icontable"><td valign="top"><xsl:apply-templates/></td></xsl:template>
|
||||
<xsl:template match="tablecell" mode="embedded"><td valign="top"><xsl:apply-templates mode="embedded"/></td></xsl:template>
|
||||
|
||||
<!-- TABLEROW -->
|
||||
<xsl:template match="tablerow"><tr><xsl:apply-templates /></tr></xsl:template>
|
||||
<xsl:template match="tablerow" mode="icontable"><tr><xsl:apply-templates mode="icontable"/></tr></xsl:template>
|
||||
<xsl:template match="tablerow" mode="embedded"><tr><xsl:apply-templates mode="embedded"/></tr></xsl:template>
|
||||
|
||||
<!-- TITLE -->
|
||||
<xsl:template match="title"/>
|
||||
|
||||
<!-- TOPIC -->
|
||||
<xsl:template match="topic"/>
|
||||
|
||||
<!-- VARIABLE -->
|
||||
<xsl:template match="variable"><a name="{@id}"></a><xsl:apply-templates /></xsl:template>
|
||||
<xsl:template match="variable" mode="embedded"><a name="{@id}"></a><xsl:apply-templates mode="embedded"/></xsl:template>
|
||||
|
||||
<xsl:template match="text()">
|
||||
<xsl:call-template name="brand">
|
||||
<xsl:with-param name="string"><xsl:value-of select="."/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="text()" mode="embedded">
|
||||
<xsl:call-template name="brand">
|
||||
<xsl:with-param name="string"><xsl:value-of select="."/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- In case of missing help files -->
|
||||
<xsl:template match="help-id-missing"><xsl:value-of select="$Id"/></xsl:template>
|
||||
|
||||
<!--
|
||||
###################
|
||||
# NAMED TEMPLATES #
|
||||
###################
|
||||
//-->
|
||||
|
||||
<!-- Branding -->
|
||||
<xsl:template name="brand" >
|
||||
<xsl:param name="string"/>
|
||||
|
||||
<xsl:choose>
|
||||
|
||||
<xsl:when test="contains($string,$brand1)">
|
||||
<xsl:variable name="newstr">
|
||||
<xsl:value-of select="substring-before($string,$brand1)"/>
|
||||
<xsl:value-of select="$productname"/>
|
||||
<xsl:value-of select="substring-after($string,$brand1)"/>
|
||||
</xsl:variable>
|
||||
<xsl:call-template name="brand">
|
||||
<xsl:with-param name="string" select="$newstr"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:when test="contains($string,$brand2)">
|
||||
<xsl:variable name="newstr">
|
||||
<xsl:value-of select="substring-before($string,$brand2)"/>
|
||||
<xsl:value-of select="$pversion"/>
|
||||
<xsl:value-of select="substring-after($string,$brand2)"/>
|
||||
</xsl:variable>
|
||||
<xsl:call-template name="brand">
|
||||
<xsl:with-param name="string" select="$newstr"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:when test="contains($string,$brand3)">
|
||||
<xsl:variable name="newstr">
|
||||
<xsl:value-of select="substring-before($string,$brand3)"/>
|
||||
<xsl:value-of select="$productname"/>
|
||||
<xsl:value-of select="substring-after($string,$brand3)"/>
|
||||
</xsl:variable>
|
||||
<xsl:call-template name="brand">
|
||||
<xsl:with-param name="string" select="$newstr"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:when test="contains($string,$brand4)">
|
||||
<xsl:variable name="newstr">
|
||||
<xsl:value-of select="substring-before($string,$brand4)"/>
|
||||
<xsl:value-of select="$pversion"/>
|
||||
<xsl:value-of select="substring-after($string,$brand4)"/>
|
||||
</xsl:variable>
|
||||
<xsl:call-template name="brand">
|
||||
<xsl:with-param name="string" select="$newstr"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$string"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- Insert Paragraph -->
|
||||
<xsl:template name="insertpara">
|
||||
<xsl:variable name="role">
|
||||
<xsl:choose>
|
||||
<xsl:when test="ancestor::table">
|
||||
<xsl:value-of select="concat(@role,'intable')"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="@role"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<p class="{$role}"><xsl:apply-templates /></p>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Insert "How to get Link" -->
|
||||
<xsl:template name="insert_howtoget">
|
||||
<xsl:param name="linkhref" />
|
||||
<xsl:variable name="archive" select="'shared'"/>
|
||||
<xsl:variable name="tmp_href"><xsl:value-of select="concat($urlpre,'shared/text/shared/00/00000004.xhp',$urlpost)"/></xsl:variable>
|
||||
<xsl:variable name="tmp_doc" select="document($tmp_href)"/>
|
||||
<table class="howtoget" width="100%" border="1" cellpadding="3" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<p class="howtogetheader"><xsl:apply-templates select="$tmp_doc//variable[@id='wie']"/></p>
|
||||
<div class="howtogetbody">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$linkhref = ''"> <!-- new style -->
|
||||
<xsl:apply-templates/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise> <!-- old style -->
|
||||
<xsl:variable name="archive1"><xsl:value-of select="concat(substring-before(substring-after($linkhref,'text/'),'/'),'/')"/></xsl:variable>
|
||||
<xsl:variable name="href"><xsl:value-of select="concat($urlpre,$archive1,substring-before($linkhref,'#'),$urlpost)"/></xsl:variable>
|
||||
<xsl:variable name="anc"><xsl:value-of select="substring-after($linkhref,'#')"/></xsl:variable>
|
||||
<xsl:variable name="docum" select="document($href)"/>
|
||||
|
||||
<xsl:call-template name="insertembed">
|
||||
<xsl:with-param name="doc" select="$docum" />
|
||||
<xsl:with-param name="anchor" select="$anc" />
|
||||
</xsl:call-template>
|
||||
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Create a link -->
|
||||
<xsl:template name="createlink">
|
||||
<xsl:variable name="archive"><xsl:value-of select="concat(substring-before(substring-after(@href,'text/'),'/'),'/')"/></xsl:variable>
|
||||
<xsl:variable name="dbpostfix"><xsl:call-template name="createDBpostfix"><xsl:with-param name="archive" select="$archive"/></xsl:call-template></xsl:variable>
|
||||
<xsl:choose>
|
||||
<xsl:when test="starts-with(@href,'http://') or starts-with(@href,'https://')"> <!-- web links -->
|
||||
<a href="{@href}"><xsl:apply-templates /></a>
|
||||
</xsl:when>
|
||||
<xsl:when test="contains(@href,'#')">
|
||||
<xsl:variable name="anchor"><xsl:value-of select="concat('#',substring-after(@href,'#'))"/></xsl:variable>
|
||||
<xsl:variable name="href"><xsl:value-of select="concat($linkprefix,$archive,substring-before(@href,'#'),$linkpostfix,$dbpostfix,$anchor)"/></xsl:variable>
|
||||
<a href="{$href}"><xsl:apply-templates /></a>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:variable name="href"><xsl:value-of select="concat($linkprefix,$archive,@href,$linkpostfix,$dbpostfix)"/></xsl:variable>
|
||||
<a href="{$href}"><xsl:apply-templates /></a>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Insert Note, Warning, or Tip -->
|
||||
<xsl:template name="insertnote">
|
||||
<xsl:param name="type" /> <!-- note, tip, or warning -->
|
||||
<xsl:variable name="imgsrc">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$type='note'"><xsl:value-of select="$note_img"/></xsl:when>
|
||||
<xsl:when test="$type='tip'"><xsl:value-of select="$tip_img"/></xsl:when>
|
||||
<xsl:when test="$type='warning'"><xsl:value-of select="$warning_img"/></xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="dbpostfix"><xsl:call-template name="createDBpostfix"><xsl:with-param name="archive" select="'shared'"/></xsl:call-template></xsl:variable>
|
||||
<xsl:variable name="alt">
|
||||
<xsl:variable name="href"><xsl:value-of select="concat($urlpre,'shared/',$alttext,$urlpost,$dbpostfix)"/></xsl:variable>
|
||||
<xsl:variable name="anchor"><xsl:value-of select="concat('alt_',$type)"/></xsl:variable>
|
||||
<xsl:variable name="doc" select="document($href)"/>
|
||||
<xsl:apply-templates select="$doc//variable[@id=$anchor]" mode="embedded"/>
|
||||
</xsl:variable>
|
||||
<div class="{$type}">
|
||||
<table border="0" class="{$type}" cellspacing="0" cellpadding="5">
|
||||
<tr>
|
||||
<td><img src="{$imgsrc}" alt="{$alt}" title="{$alt}"/></td>
|
||||
<td><xsl:apply-templates /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<br/>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Insert a heading -->
|
||||
<xsl:template name="insertheading">
|
||||
<xsl:param name="level" />
|
||||
<xsl:param name="embedded" />
|
||||
<xsl:text disable-output-escaping="yes"><h</xsl:text><xsl:value-of select="$level"/><xsl:text disable-output-escaping="yes">></xsl:text>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$embedded = 'yes'">
|
||||
<xsl:apply-templates mode="embedded"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:text disable-output-escaping="yes"></h</xsl:text><xsl:value-of select="$level"/><xsl:text disable-output-escaping="yes">></xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Evaluate a case or caseinline switch -->
|
||||
<xsl:template name="insertcase">
|
||||
<xsl:param name="embedded" />
|
||||
<xsl:choose>
|
||||
<xsl:when test="parent::switch[@select='sys'] or parent::switchinline[@select='sys']">
|
||||
<xsl:if test="@select = $System">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$embedded = 'yes'">
|
||||
<xsl:apply-templates mode="embedded"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:if>
|
||||
</xsl:when>
|
||||
<xsl:when test="parent::switch[@select='appl'] or parent::switchinline[@select='appl']">
|
||||
<xsl:if test="@select = $appl">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$embedded = 'yes'">
|
||||
<xsl:apply-templates mode="embedded"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:if>
|
||||
</xsl:when>
|
||||
<xsl:when test="parent::switch[@select='distrib'] or parent::switchinline[@select='distrib']">
|
||||
<xsl:if test="@select = $distrib">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$embedded = 'yes'">
|
||||
<xsl:apply-templates mode="embedded"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:if>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Evaluate a default or defaultinline switch -->
|
||||
<xsl:template name="insertdefault">
|
||||
<xsl:param name="embedded" />
|
||||
|
||||
<xsl:choose>
|
||||
<xsl:when test="parent::switch[@select='sys'] or parent::switchinline[@select='sys']">
|
||||
<xsl:if test="not(../child::case[@select=$System]) and not(../child::caseinline[@select=$System])">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$embedded = 'yes'">
|
||||
<xsl:apply-templates mode="embedded"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:if>
|
||||
</xsl:when>
|
||||
<xsl:when test="parent::switch[@select='appl'] or parent::switchinline[@select='appl']">
|
||||
<xsl:if test="not(../child::case[@select=$appl]) and not(../child::caseinline[@select=$appl])">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$embedded = 'yes'">
|
||||
<xsl:apply-templates mode="embedded"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:if>
|
||||
</xsl:when>
|
||||
<xsl:when test="parent::switch[@select='distrib'] or parent::switchinline[@select='distrib']">
|
||||
<xsl:if test="not(../child::case[@select=$distrib]) and not(../child::caseinline[@select=$distrib])">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$embedded = 'yes'">
|
||||
<xsl:apply-templates mode="embedded"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:if>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<!-- evaluate embeds -->
|
||||
<xsl:template name="insertembed">
|
||||
<xsl:param name="doc" />
|
||||
<xsl:param name="anchor" />
|
||||
<!-- different embed targets (also falsely used embed instead embedvar) -->
|
||||
<xsl:choose>
|
||||
<xsl:when test="$doc//section[@id=$anchor]"> <!-- first test for a section of that name -->
|
||||
<xsl:apply-templates select="$doc//section[@id=$anchor]" mode="embedded"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="$doc//paragraph[@id=$anchor]"> <!-- then test for a para of that name -->
|
||||
<p class="embedded">
|
||||
<xsl:apply-templates select="$doc//paragraph[@id=$anchor]" mode="embedded"/>
|
||||
</p>
|
||||
</xsl:when>
|
||||
<xsl:when test="$doc//variable[@id=$anchor]"> <!-- then test for a variable of that name -->
|
||||
<p class="embedded">
|
||||
<xsl:apply-templates select="$doc//variable[@id=$anchor]" mode="embedded"/>
|
||||
</p>
|
||||
</xsl:when>
|
||||
<xsl:otherwise> <!-- then give up -->
|
||||
<p class="bug">D'oh! You found a bug (<xsl:value-of select="@href"/> not found).</p>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Insert an image -->
|
||||
<xsl:template name="insertimage">
|
||||
|
||||
<xsl:variable name="fpath">
|
||||
<xsl:call-template name="getfpath">
|
||||
<xsl:with-param name="s"><xsl:value-of select="@src"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:variable name="fname">
|
||||
<xsl:call-template name="getfname">
|
||||
<xsl:with-param name="s"><xsl:value-of select="@src"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:variable name="src">
|
||||
<xsl:choose>
|
||||
<xsl:when test="not($ExtensionId='') and starts-with(@src,$ExtensionId)">
|
||||
<xsl:value-of select="concat($ExtensionPath,'/',@src)"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:choose>
|
||||
<xsl:when test="(@localize='true') and not($lang='en-US')">
|
||||
<xsl:value-of select="concat($img_url_prefix,$fpath,$lang,'/',$fname)"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="concat($img_url_prefix,$fpath,$fname)"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
|
||||
<!--<xsl:variable name="src"><xsl:value-of select="concat($img_url_prefix,@src)"/></xsl:variable>-->
|
||||
<xsl:variable name="alt"><xsl:value-of select="./alt"/></xsl:variable>
|
||||
<xsl:variable name="width" select="''"/> <!-- Images don't all have the correct size -->
|
||||
<xsl:variable name="height" select="''"/><!-- Image don't all have the correct size -->
|
||||
<img src="{$src}" alt="{$alt}" title="{$alt}">
|
||||
<xsl:if test="not($width='')"><xsl:attribute name="width"><xsl:value-of select="$width"/></xsl:attribute></xsl:if>
|
||||
<xsl:if test="not($height='')"><xsl:attribute name="height"><xsl:value-of select="$height"/></xsl:attribute></xsl:if>
|
||||
</img>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Insert a Table -->
|
||||
<xsl:template name="inserttable">
|
||||
<xsl:variable name="imgsrc"> <!-- see if we are in an image table -->
|
||||
<xsl:value-of select="tablerow/tablecell[1]/paragraph[1]/image/@src"/>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:choose>
|
||||
|
||||
<xsl:when test="count(descendant::tablecell)=1">
|
||||
<table border="0" class="onecell" cellpadding="0" cellspacing="0">
|
||||
<xsl:apply-templates />
|
||||
</table>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:when test="descendant::tablecell[1]/descendant::image">
|
||||
<table border="0" class="icontable" cellpadding="5" cellspacing="0">
|
||||
<xsl:apply-templates mode="icontable"/>
|
||||
</table>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:when test="@class='wide'">
|
||||
<table border="1" class="{@class}" cellpadding="0" cellspacing="0" width="100%" >
|
||||
<xsl:apply-templates />
|
||||
</table>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:when test="not(@class='')">
|
||||
<table border="1" class="{@class}" cellpadding="0" cellspacing="0" >
|
||||
<xsl:apply-templates />
|
||||
</table>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:otherwise>
|
||||
<table border="1" class="border" cellpadding="0" cellspacing="0" >
|
||||
<xsl:apply-templates />
|
||||
</table>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
|
||||
<br/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="resolveembed">
|
||||
<div class="embedded">
|
||||
<xsl:variable name="archive"><xsl:value-of select="concat(substring-before(substring-after(@href,'text/'),'/'),'/')"/></xsl:variable>
|
||||
<xsl:variable name="dbpostfix"><xsl:call-template name="createDBpostfix"><xsl:with-param name="archive" select="$archive"/></xsl:call-template></xsl:variable>
|
||||
<xsl:variable name="href"><xsl:value-of select="concat($urlpre,$archive,substring-before(@href,'#'),$urlpost,$dbpostfix)"/></xsl:variable>
|
||||
<xsl:variable name="anc"><xsl:value-of select="substring-after(@href,'#')"/></xsl:variable>
|
||||
<xsl:variable name="docum" select="document($href)"/>
|
||||
|
||||
<xsl:call-template name="insertembed">
|
||||
<xsl:with-param name="doc" select="$docum" />
|
||||
<xsl:with-param name="anchor" select="$anc" />
|
||||
</xsl:call-template>
|
||||
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="resolveembedvar">
|
||||
<xsl:if test="not(@href='text/shared/00/00000004.xhp#wie')"> <!-- special treatment if howtoget links -->
|
||||
<xsl:variable name="archive"><xsl:value-of select="concat(substring-before(substring-after(@href,'text/'),'/'),'/')"/></xsl:variable>
|
||||
<xsl:variable name="dbpostfix"><xsl:call-template name="createDBpostfix"><xsl:with-param name="archive" select="$archive"/></xsl:call-template></xsl:variable>
|
||||
<xsl:variable name="href"><xsl:value-of select="concat($urlpre,$archive,substring-before(@href,'#'),$urlpost,$dbpostfix)"/></xsl:variable>
|
||||
<xsl:variable name="anchor"><xsl:value-of select="substring-after(@href,'#')"/></xsl:variable>
|
||||
<xsl:variable name="doc" select="document($href)"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$doc//variable[@id=$anchor]"> <!-- test for a variable of that name -->
|
||||
<xsl:apply-templates select="$doc//variable[@id=$anchor]" mode="embedded"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise> <!-- or give up -->
|
||||
<span class="bug">[<xsl:value-of select="@href"/> not found].</span>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Apply -->
|
||||
<xsl:template name="apply">
|
||||
<xsl:param name="embedded" />
|
||||
<xsl:choose>
|
||||
<xsl:when test="$embedded = 'yes'">
|
||||
<xsl:apply-templates mode="embedded"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="getfpath">
|
||||
<xsl:param name="s"/>
|
||||
<xsl:param name="p"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains($s,'/')">
|
||||
<xsl:call-template name="getfpath">
|
||||
<xsl:with-param name="p"><xsl:value-of select="concat($p,substring-before($s,'/'),'/')"/></xsl:with-param>
|
||||
<xsl:with-param name="s"><xsl:value-of select="substring-after($s,'/')"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$p"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="getfname">
|
||||
<xsl:param name="s"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains($s,'/')">
|
||||
<xsl:call-template name="getfname">
|
||||
<xsl:with-param name="s"><xsl:value-of select="substring-after($s,'/')"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$s"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="createDBpostfix">
|
||||
<xsl:param name="archive"/>
|
||||
<xsl:variable name="newDB">
|
||||
<xsl:choose>
|
||||
<xsl:when test="(substring($archive,1,6) = 'shared')"><xsl:value-of select="$Database"/></xsl:when>
|
||||
<xsl:otherwise><xsl:value-of select="substring-before($archive,'/')"/></xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:value-of select="concat($am,'DbPAR=',$newDB)"/>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
@ -0,0 +1,94 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*************************************************************/
|
||||
|
||||
/*
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ OPENOFFICE.ORG 2.0 HELP +
|
||||
+ DEFAULT STYLESHEET +
|
||||
+ CHINESE SIMPL +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ LAST CHANGES: 24-MAR-2005 +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
*/
|
||||
|
||||
|
||||
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
|
||||
{ font-family: 方正宋体,"MSung Light SC",SimSun,FZSongYi,FZShuSong,NSimSun,"Andale Sans UI","Arial Unicode MS","Lucida Sans Unicode",Song; }
|
||||
|
||||
.code, .codeintable, .example, .exampleintable, .literal, .literalintable, .path, .pathintable
|
||||
{ font-family: 方正宋体,"MSung Light SC",Cumberland,Courier New,Courier,"Lucida Sans Typewriter","Lucida Typewriter",Monaco,Monospaced; margin-top: 1pt; margin-bottom: 1pt;}
|
||||
|
||||
.acronym
|
||||
{ font-weight: bold; }
|
||||
|
||||
.related
|
||||
{ font-weight: bold; margin-top:20pt; border-top: 1px solid black;}
|
||||
|
||||
.emph, .menuitem, .keycode
|
||||
{ font-weight: bold; }
|
||||
|
||||
.tablehead, .tableheadintable
|
||||
{ font-weight: bold; margin-top: 0px;}
|
||||
|
||||
.howtogetheader
|
||||
{ font-weight: bold; border: 1px solid #999999; background: #FFFFFF; padding: 3px;}
|
||||
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{ margin-bottom: 5pt; }
|
||||
|
||||
p, td
|
||||
{ font-size: 10pt; }
|
||||
|
||||
h1
|
||||
{ font-size: 18pt; border-bottom: 1px solid black; padding-bottom: 6px; margin-bottom: 6px;}
|
||||
|
||||
h2
|
||||
{ font-size: 14pt; }
|
||||
|
||||
h3
|
||||
{ font-size: 12pt; }
|
||||
|
||||
h4, h5, h6
|
||||
{ font-size: 10pt; }
|
||||
|
||||
.relatedtopics
|
||||
{ font-weight: normal; }
|
||||
|
||||
.relatedbody
|
||||
{ margin-top: 2px; margin-bottom: 2px; margin-left: 5px; }
|
||||
|
||||
.howtoget
|
||||
{ background:#EEEEEE;}
|
||||
|
||||
.howtogetbody
|
||||
{ background:#EEEEEE;}
|
||||
|
||||
.wide
|
||||
{ width: 100%; }
|
||||
|
||||
.topalign
|
||||
{ vertical-align: top; border: 1px;}
|
||||
|
||||
.bug
|
||||
{ color: red; border: 1px solid red;}
|
||||
|
||||
.debug
|
||||
{ border: 1px solid black; padding: 3px; display: none;}
|
@ -0,0 +1,114 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*************************************************************/
|
||||
|
||||
/*
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ OPENOFFICE.ORG 2.0 HELP +
|
||||
+ HIGH CONTRAST #1 STYLESHEET +
|
||||
+ CHINESE SIMPL +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ LAST CHANGES: 24-MAR-2005 +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
*/
|
||||
|
||||
|
||||
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
|
||||
{ font-family: 方正宋体,"MSung Light SC",SimSun,FZSongYi,FZShuSong,NSimSun,"Andale Sans UI","Arial Unicode MS","Lucida Sans Unicode",Song; }
|
||||
|
||||
.code, .codeintable, .example, .exampleintable, .literal, .literalintable, .path, .pathintable
|
||||
{ font-family: 方正宋体,"MSung Light SC",Cumberland,Courier New,Courier,"Lucida Sans Typewriter","Lucida Typewriter",Monaco,Monospaced; margin-top: 1pt; margin-bottom: 1pt;}
|
||||
|
||||
.acronym
|
||||
{ font-weight: bold; }
|
||||
|
||||
.related
|
||||
{ font-weight: bold; margin-top:20pt; border-top: 1px solid black;}
|
||||
|
||||
.emph, .menuitem, .keycode
|
||||
{ font-weight: bold; }
|
||||
|
||||
.tablehead, .tableheadintable
|
||||
{ font-weight: bold; margin-top: 0px;}
|
||||
|
||||
.howtogetheader
|
||||
{ font-weight: bold; padding: 3px;}
|
||||
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{ margin-bottom: 5pt; }
|
||||
|
||||
p, td
|
||||
{ font-size: 10pt; }
|
||||
|
||||
h1
|
||||
{ font-size: 18pt; border-bottom: 1px solid black; padding-bottom: 6px; margin-bottom: 6px;}
|
||||
|
||||
h2
|
||||
{ font-size: 14pt; }
|
||||
|
||||
h3
|
||||
{ font-size: 12pt; }
|
||||
|
||||
h4, h5, h6
|
||||
{ font-size: 10pt; }
|
||||
|
||||
.relatedtopics
|
||||
{ font-weight: normal; }
|
||||
|
||||
.relatedbody
|
||||
{ margin-top: 2px; margin-bottom: 2px; margin-left: 5px; }
|
||||
|
||||
.wide
|
||||
{ width: 100%; }
|
||||
|
||||
.topalign
|
||||
{ vertical-align: top; border: 1px;}
|
||||
|
||||
.bug
|
||||
{ color: red; border: 1px solid red;}
|
||||
|
||||
.debug
|
||||
{ border: 1px solid black; padding: 3px; display: none;}
|
||||
|
||||
/* HIGH CONTRAST SPECIFIC SETTINGS */
|
||||
|
||||
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
|
||||
{ background: #000000; color: #FFFF00;}
|
||||
|
||||
.related
|
||||
{ border-top: 1px solid #FFFF00; }
|
||||
|
||||
.howtogetheader
|
||||
{border: 1px solid #EFEFEF; background: #000000;}
|
||||
|
||||
h1
|
||||
{ border-bottom: 1px solid #FFFF00; ]
|
||||
|
||||
.howtoget
|
||||
{ background:#000000;}
|
||||
|
||||
.howtogetbody
|
||||
{ background:#000000;}
|
||||
|
||||
.debug
|
||||
{ border: 1px solid red; padding: 3px; display: none;}
|
||||
|
||||
a
|
||||
{ color: #FFFF00; }
|
@ -0,0 +1,114 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*************************************************************/
|
||||
|
||||
/*
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ OPENOFFICE.ORG 2.0 HELP +
|
||||
+ HIGH CONTRAST #2 STYLESHEET +
|
||||
+ CHINESE SIMPL +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ LAST CHANGES: 24-MAR-2005 +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
*/
|
||||
|
||||
|
||||
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
|
||||
{ font-family: 方正宋体,"MSung Light SC",SimSun,FZSongYi,FZShuSong,NSimSun,"Andale Sans UI","Arial Unicode MS","Lucida Sans Unicode",Song; }
|
||||
|
||||
.code, .codeintable, .example, .exampleintable, .literal, .literalintable, .path, .pathintable
|
||||
{ font-family: 方正宋体,"MSung Light SC",Cumberland,Courier New,Courier,"Lucida Sans Typewriter","Lucida Typewriter",Monaco,Monospaced; margin-top: 1pt; margin-bottom: 1pt;}
|
||||
|
||||
.acronym
|
||||
{ font-weight: bold; }
|
||||
|
||||
.related
|
||||
{ font-weight: bold; margin-top:20pt; border-top: 1px solid black;}
|
||||
|
||||
.emph, .menuitem, .keycode
|
||||
{ font-weight: bold; }
|
||||
|
||||
.tablehead, .tableheadintable
|
||||
{ font-weight: bold; margin-top: 0px;}
|
||||
|
||||
.howtogetheader
|
||||
{ font-weight: bold; padding: 3px;}
|
||||
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{ margin-bottom: 5pt; }
|
||||
|
||||
p, td
|
||||
{ font-size: 10pt; }
|
||||
|
||||
h1
|
||||
{ font-size: 18pt; border-bottom: 1px solid black; padding-bottom: 6px; margin-bottom: 6px;}
|
||||
|
||||
h2
|
||||
{ font-size: 14pt; }
|
||||
|
||||
h3
|
||||
{ font-size: 12pt; }
|
||||
|
||||
h4, h5, h6
|
||||
{ font-size: 10pt; }
|
||||
|
||||
.relatedtopics
|
||||
{ font-weight: normal; }
|
||||
|
||||
.relatedbody
|
||||
{ margin-top: 2px; margin-bottom: 2px; margin-left: 5px; }
|
||||
|
||||
.wide
|
||||
{ width: 100%; }
|
||||
|
||||
.topalign
|
||||
{ vertical-align: top; border: 1px;}
|
||||
|
||||
.bug
|
||||
{ color: red; border: 1px solid red;}
|
||||
|
||||
.debug
|
||||
{ border: 1px solid black; padding: 3px; display: none;}
|
||||
|
||||
/* HIGH CONTRAST SPECIFIC SETTINGS */
|
||||
|
||||
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
|
||||
{ background: #000000; color: #00FF00;}
|
||||
|
||||
.related
|
||||
{ border-top: 1px solid #00FF00; }
|
||||
|
||||
.howtogetheader
|
||||
{border: 1px solid #EFEFEF; background: #000000;}
|
||||
|
||||
h1
|
||||
{ border-bottom: 1px solid #00FF00; ]
|
||||
|
||||
.howtoget
|
||||
{ background:#000000;}
|
||||
|
||||
.howtogetbody
|
||||
{ background:#000000;}
|
||||
|
||||
.debug
|
||||
{ border: 1px solid red; padding: 3px; display: none;}
|
||||
|
||||
a
|
||||
{ color: #00FF00; }
|
@ -0,0 +1,114 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*************************************************************/
|
||||
|
||||
/*
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ OPENOFFICE.ORG 2.0 HELP +
|
||||
+ HIGH CONTRAST BLACK STYLESHEET +
|
||||
+ CHINESE SIMPL +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ LAST CHANGES: 24-MAR-2005 +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
*/
|
||||
|
||||
|
||||
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
|
||||
{ font-family: 方正宋体,"MSung Light SC",SimSun,FZSongYi,FZShuSong,NSimSun,"Andale Sans UI","Arial Unicode MS","Lucida Sans Unicode",Song; }
|
||||
|
||||
.code, .codeintable, .example, .exampleintable, .literal, .literalintable, .path, .pathintable
|
||||
{ font-family: 方正宋体,"MSung Light SC",Cumberland,Courier New,Courier,"Lucida Sans Typewriter","Lucida Typewriter",Monaco,Monospaced; margin-top: 1pt; margin-bottom: 1pt;}
|
||||
|
||||
.acronym
|
||||
{ font-weight: bold; }
|
||||
|
||||
.related
|
||||
{ font-weight: bold; margin-top:20pt; border-top: 1px solid black;}
|
||||
|
||||
.emph, .menuitem, .keycode
|
||||
{ font-weight: bold; }
|
||||
|
||||
.tablehead, .tableheadintable
|
||||
{ font-weight: bold; margin-top: 0px;}
|
||||
|
||||
.howtogetheader
|
||||
{ font-weight: bold; padding: 3px;}
|
||||
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{ margin-bottom: 5pt; }
|
||||
|
||||
p, td
|
||||
{ font-size: 10pt; }
|
||||
|
||||
h1
|
||||
{ font-size: 18pt; border-bottom: 1px solid black; padding-bottom: 6px; margin-bottom: 6px;}
|
||||
|
||||
h2
|
||||
{ font-size: 14pt; }
|
||||
|
||||
h3
|
||||
{ font-size: 12pt; }
|
||||
|
||||
h4, h5, h6
|
||||
{ font-size: 10pt; }
|
||||
|
||||
.relatedtopics
|
||||
{ font-weight: normal; }
|
||||
|
||||
.relatedbody
|
||||
{ margin-top: 2px; margin-bottom: 2px; margin-left: 5px; }
|
||||
|
||||
.wide
|
||||
{ width: 100%; }
|
||||
|
||||
.topalign
|
||||
{ vertical-align: top; border: 1px;}
|
||||
|
||||
.bug
|
||||
{ color: red; border: 1px solid red;}
|
||||
|
||||
.debug
|
||||
{ border: 1px solid black; padding: 3px; display: none;}
|
||||
|
||||
/* HIGH CONTRAST SPECIFIC SETTINGS */
|
||||
|
||||
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
|
||||
{ background: #000000; color: #FFFFFF;}
|
||||
|
||||
.related
|
||||
{ border-top: 1px solid #FFFFFF; }
|
||||
|
||||
.howtogetheader
|
||||
{border: 1px solid #FFFFFF; background: #000000;}
|
||||
|
||||
h1
|
||||
{ border-bottom: 1px solid #FFFFFF; ]
|
||||
|
||||
.howtoget
|
||||
{ background:#000000;}
|
||||
|
||||
.howtogetbody
|
||||
{ background:#000000;}
|
||||
|
||||
.debug
|
||||
{ border: 1px solid red; padding: 3px; display: none;}
|
||||
|
||||
a
|
||||
{ color: #FFFFFF; }
|
@ -0,0 +1,114 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*************************************************************/
|
||||
|
||||
/*
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ OPENOFFICE.ORG 2.0 HELP +
|
||||
+ HIGH CONTRAST WHITE STYLESHEET +
|
||||
+ CHINESE SIMPL +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ LAST CHANGES: 24-MAR-2005 +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
*/
|
||||
|
||||
|
||||
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
|
||||
{ font-family: 方正宋体,"MSung Light SC",SimSun,FZSongYi,FZShuSong,NSimSun,"Andale Sans UI","Arial Unicode MS","Lucida Sans Unicode",Song; }
|
||||
|
||||
.code, .codeintable, .example, .exampleintable, .literal, .literalintable, .path, .pathintable
|
||||
{ font-family: 方正宋体,"MSung Light SC",Cumberland,Courier New,Courier,"Lucida Sans Typewriter","Lucida Typewriter",Monaco,Monospaced; margin-top: 1pt; margin-bottom: 1pt;}
|
||||
|
||||
.acronym
|
||||
{ font-weight: bold; }
|
||||
|
||||
.related
|
||||
{ font-weight: bold; margin-top:20pt; border-top: 1px solid black;}
|
||||
|
||||
.emph, .menuitem, .keycode
|
||||
{ font-weight: bold; }
|
||||
|
||||
.tablehead, .tableheadintable
|
||||
{ font-weight: bold; margin-top: 0px;}
|
||||
|
||||
.howtogetheader
|
||||
{ font-weight: bold; padding: 3px;}
|
||||
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{ margin-bottom: 5pt; }
|
||||
|
||||
p, td
|
||||
{ font-size: 10pt; }
|
||||
|
||||
h1
|
||||
{ font-size: 18pt; border-bottom: 1px solid black; padding-bottom: 6px; margin-bottom: 6px;}
|
||||
|
||||
h2
|
||||
{ font-size: 14pt; }
|
||||
|
||||
h3
|
||||
{ font-size: 12pt; }
|
||||
|
||||
h4, h5, h6
|
||||
{ font-size: 10pt; }
|
||||
|
||||
.relatedtopics
|
||||
{ font-weight: normal; }
|
||||
|
||||
.relatedbody
|
||||
{ margin-top: 2px; margin-bottom: 2px; margin-left: 5px; }
|
||||
|
||||
.wide
|
||||
{ width: 100%; }
|
||||
|
||||
.topalign
|
||||
{ vertical-align: top; border: 1px;}
|
||||
|
||||
.bug
|
||||
{ color: red; border: 1px solid red;}
|
||||
|
||||
.debug
|
||||
{ border: 1px solid black; padding: 3px; display: none;}
|
||||
|
||||
/* HIGH CONTRAST SPECIFIC SETTINGS */
|
||||
|
||||
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
|
||||
{ background: #FFFFFF; color: #000000;}
|
||||
|
||||
.related
|
||||
{ border-top: 1px solid #000000; }
|
||||
|
||||
.howtogetheader
|
||||
{border: 1px solid #000000; background: #FFFFFF;}
|
||||
|
||||
h1
|
||||
{ border-bottom: 1px solid #000000; ]
|
||||
|
||||
.howtoget
|
||||
{ background:#FFFFFF;}
|
||||
|
||||
.howtogetbody
|
||||
{ background:#FFFFFF;}
|
||||
|
||||
.debug
|
||||
{ border: 1px solid red; padding: 3px; display: none;}
|
||||
|
||||
a
|
||||
{ color: #000000; }
|
@ -0,0 +1,30 @@
|
||||
###############################################################
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
###############################################################
|
||||
|
||||
|
||||
Title=%PRODUCTNAME Basic
|
||||
|
||||
Language=zh-CN
|
||||
Order=7
|
||||
Start=text%2Fsbasic%2Fshared%2Fmain0601.xhp
|
||||
Heading=headingheading
|
||||
Program=BASIC
|
||||
07.07.04 00:00:00
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,30 @@
|
||||
###############################################################
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
###############################################################
|
||||
|
||||
|
||||
Title=%PRODUCTNAME Calc
|
||||
|
||||
Language=zh-CN
|
||||
Order=3
|
||||
Start=text%2Fscalc%2Fmain0000.xhp
|
||||
Heading=headingheading
|
||||
Program=CALC
|
||||
07.07.04 00:00:00
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,190 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--***********************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***********************************************************-->
|
||||
<tree_view version="24-Aug-2004">
|
||||
<help_section application="scalc" id="08" title="电子表格">
|
||||
<node id="0801" title="一般信息和用户界面的使用">
|
||||
<topic id="scalc/text/scalc/main0000.xhp">欢迎使用 %PRODUCTNAME Calc 帮助</topic>
|
||||
<topic id="scalc/text/scalc/main0503.xhp">%PRODUCTNAME Calc 功能</topic>
|
||||
<topic id="scalc/text/scalc/guide/keyboard.xhp">快捷键(%PRODUCTNAME Calc 辅助功能)</topic>
|
||||
<topic id="scalc/text/scalc/04/01020000.xhp">电子表格的快捷键</topic>
|
||||
<topic id="scalc/text/scalc/05/02140000.xhp">%PRODUCTNAME Calc 中的错误代码</topic>
|
||||
<topic id="scalc/text/scalc/01/04060112.xhp">%PRODUCTNAME Calc 中用于编程的加载宏</topic>
|
||||
<topic id="scalc/text/scalc/guide/main.xhp">%PRODUCTNAME Calc 使用说明</topic>
|
||||
</node>
|
||||
<node id="0802" title="命令和菜单引用">
|
||||
<node id="080201" title="菜单">
|
||||
<topic id="scalc/text/scalc/main0100.xhp">菜单</topic>
|
||||
<topic id="scalc/text/scalc/main0101.xhp">文件</topic>
|
||||
<topic id="scalc/text/scalc/main0102.xhp">编辑</topic>
|
||||
<topic id="scalc/text/scalc/main0103.xhp">视图</topic>
|
||||
<topic id="scalc/text/scalc/main0104.xhp">插入</topic>
|
||||
<topic id="scalc/text/scalc/main0105.xhp">格式</topic>
|
||||
<topic id="scalc/text/scalc/main0106.xhp">工具</topic>
|
||||
<topic id="scalc/text/scalc/main0107.xhp">窗口</topic>
|
||||
<topic id="scalc/text/scalc/main0112.xhp">数据</topic>
|
||||
</node>
|
||||
<node id="080202" title="工具栏">
|
||||
<topic id="scalc/text/scalc/main0200.xhp">工具栏</topic>
|
||||
<topic id="scalc/text/scalc/main0202.xhp">格式栏</topic>
|
||||
<topic id="scalc/text/scalc/main0203.xhp">绘图对象属性栏</topic>
|
||||
<topic id="scalc/text/scalc/main0205.xhp">文字格式栏</topic>
|
||||
<topic id="scalc/text/scalc/main0206.xhp">公式栏</topic>
|
||||
<topic id="scalc/text/scalc/main0208.xhp">状态栏</topic>
|
||||
<topic id="scalc/text/scalc/main0210.xhp">打印预览栏</topic>
|
||||
<topic id="scalc/text/scalc/main0214.xhp">图片栏</topic>
|
||||
<topic id="scalc/text/scalc/main0218.xhp">工具栏</topic>
|
||||
<topic id="shared/text/shared/main0201.xhp">标准栏</topic>
|
||||
<topic id="shared/text/shared/main0209.xhp">超链接地址栏</topic>
|
||||
<topic id="shared/text/shared/main0212.xhp">表格数据栏</topic>
|
||||
<topic id="shared/text/shared/main0213.xhp">窗体导航栏</topic>
|
||||
<topic id="shared/text/shared/main0214.xhp">查询设计栏</topic>
|
||||
<topic id="shared/text/shared/main0226.xhp">窗体设计工具栏</topic>
|
||||
</node>
|
||||
</node>
|
||||
<node id="0803" title="函数类型和运算符">
|
||||
<topic id="scalc/text/scalc/01/04060000.xhp">函数向导</topic>
|
||||
<topic id="scalc/text/scalc/01/04060100.xhp">函数(按类别)</topic>
|
||||
<topic id="scalc/text/scalc/01/04060101.xhp">数据库函数</topic>
|
||||
<topic id="scalc/text/scalc/01/04060102.xhp">日期和时间函数</topic>
|
||||
<topic id="scalc/text/scalc/01/04060103.xhp">财务函数第一部分</topic>
|
||||
<topic id="scalc/text/scalc/01/04060119.xhp">财务函数第二部分</topic>
|
||||
<topic id="scalc/text/scalc/01/04060118.xhp">金融函数第三部分</topic>
|
||||
<topic id="scalc/text/scalc/01/04060104.xhp">信息函数</topic>
|
||||
<topic id="scalc/text/scalc/01/04060105.xhp">逻辑函数</topic>
|
||||
<topic id="scalc/text/scalc/01/04060106.xhp">数学函数</topic>
|
||||
<topic id="scalc/text/scalc/01/04060107.xhp">矩阵函数</topic>
|
||||
<topic id="scalc/text/scalc/01/04060108.xhp">统计函数</topic>
|
||||
<topic id="scalc/text/scalc/01/04060181.xhp">统计函数第一部分</topic>
|
||||
<topic id="scalc/text/scalc/01/04060182.xhp">统计函数第二部分</topic>
|
||||
<topic id="scalc/text/scalc/01/04060183.xhp">统计函数第三部分</topic>
|
||||
<topic id="scalc/text/scalc/01/04060184.xhp">统计函数第四部分</topic>
|
||||
<topic id="scalc/text/scalc/01/04060185.xhp">统计函数第五部分</topic>
|
||||
<topic id="scalc/text/scalc/01/04060109.xhp">电子表格函数</topic>
|
||||
<topic id="scalc/text/scalc/01/04060110.xhp">文字函数</topic>
|
||||
<topic id="scalc/text/scalc/01/04060111.xhp">加载宏函数</topic>
|
||||
<topic id="scalc/text/scalc/01/04060115.xhp">加载宏函数,分析函数列表第一部分</topic>
|
||||
<topic id="scalc/text/scalc/01/04060116.xhp">加载宏函数,分析函数列表第二部分</topic>
|
||||
|
||||
<topic id="scalc/text/scalc/01/04060199.xhp">%PRODUCTNAME Calc 中的运算符</topic>
|
||||
<topic id="scalc/text/scalc/guide/userdefined_function.xhp">自定义函数</topic>
|
||||
</node>
|
||||
<node id="0804" title="加载、保存、导入和导出">
|
||||
<topic id="scalc/text/scalc/guide/webquery.xhp">在表格中插入外部数据 (WebQuery)</topic>
|
||||
<topic id="scalc/text/scalc/guide/html_doc.xhp">将工作表以 HTML 格式保存和打开</topic>
|
||||
<topic id="scalc/text/scalc/guide/csv_formula.xhp">导入和导出文本文件</topic>
|
||||
</node>
|
||||
<node id="0805" title="格式化">
|
||||
<topic id="scalc/text/scalc/guide/text_rotate.xhp">旋转文字</topic>
|
||||
<topic id="scalc/text/scalc/guide/text_wrap.xhp">写入多行文字</topic>
|
||||
<topic id="scalc/text/scalc/guide/text_numbers.xhp">将数字格式化为文本</topic>
|
||||
<topic id="scalc/text/scalc/guide/super_subscript.xhp">文字上标/下标</topic>
|
||||
<topic id="scalc/text/scalc/guide/row_height.xhp">改变行高或列宽</topic>
|
||||
<topic id="scalc/text/scalc/guide/cellstyle_conditional.xhp">应用条件格式</topic>
|
||||
<topic id="scalc/text/scalc/guide/cellstyle_minusvalue.xhp">突出显示负数</topic>
|
||||
<topic id="scalc/text/scalc/guide/cellstyle_by_formula.xhp">根据公式指定的格式</topic>
|
||||
<topic id="scalc/text/scalc/guide/integer_leading_zero.xhp">输入带前置零的数字</topic>
|
||||
<topic id="scalc/text/scalc/guide/format_table.xhp">格式化电子表格</topic>
|
||||
<topic id="scalc/text/scalc/guide/format_value.xhp">格式化带小数的数字</topic>
|
||||
<topic id="scalc/text/scalc/guide/value_with_name.xhp">命名单元格</topic>
|
||||
<topic id="scalc/text/scalc/guide/table_rotate.xhp">旋转表格(转置)</topic>
|
||||
<topic id="scalc/text/scalc/guide/rename_table.xhp">重命名工作表</topic>
|
||||
<topic id="scalc/text/scalc/guide/year2000.xhp">19xx/20xx 年</topic>
|
||||
<topic id="scalc/text/scalc/guide/rounding_numbers.xhp">使用四舍五入的数字</topic>
|
||||
<topic id="scalc/text/scalc/guide/currency_format.xhp">采用货币格式的单元格</topic>
|
||||
<topic id="scalc/text/scalc/guide/autoformat.xhp">对表格使用自动套用格式</topic>
|
||||
<topic id="scalc/text/scalc/guide/note_insert.xhp">插入和编辑批注</topic>
|
||||
<topic id="scalc/text/scalc/guide/design.xhp">选择工作表主题</topic>
|
||||
<topic id="scalc/text/scalc/guide/fraction_enter.xhp">输入分数</topic>
|
||||
</node>
|
||||
<node id="0806" title="筛选和排序">
|
||||
<topic id="scalc/text/scalc/guide/filters.xhp">应用筛选</topic>
|
||||
<topic id="scalc/text/scalc/guide/specialfilter.xhp">筛选:应用高级筛选</topic>
|
||||
<!-- removed scalc/text/scalc/guide/standardfilter.xhp -->
|
||||
<topic id="scalc/text/scalc/guide/autofilter.xhp">应用自动筛选</topic>
|
||||
<topic id="scalc/text/scalc/guide/sorted_list.xhp">应用排序列表</topic>
|
||||
</node>
|
||||
<node id="0807" title="打印">
|
||||
<topic id="scalc/text/scalc/guide/print_title_row.xhp">在每一页上打印行或列</topic>
|
||||
<topic id="scalc/text/scalc/guide/print_landscape.xhp">横向打印工作表</topic>
|
||||
<topic id="scalc/text/scalc/guide/print_details.xhp">打印工作表详细资料</topic>
|
||||
<topic id="scalc/text/scalc/guide/print_exact.xhp">定义打印的页数</topic>
|
||||
</node>
|
||||
<node id="0808" title="数据区域">
|
||||
<topic id="scalc/text/scalc/guide/database_define.xhp">定义数据库区域</topic>
|
||||
<topic id="scalc/text/scalc/guide/database_filter.xhp">过滤单元格范围</topic>
|
||||
<!-- removed scalc/text/scalc/guide/database_group.xhp -->
|
||||
<topic id="scalc/text/scalc/guide/database_sort.xhp">数据排序 </topic>
|
||||
</node>
|
||||
<node id="0809" title="数据透视表">
|
||||
<topic id="scalc/text/scalc/guide/datapilot.xhp">数据透视表</topic>
|
||||
<topic id="scalc/text/scalc/guide/datapilot_createtable.xhp">创建数据透视表</topic>
|
||||
<topic id="scalc/text/scalc/guide/datapilot_deletetable.xhp">删除数据透视表</topic>
|
||||
<topic id="scalc/text/scalc/guide/datapilot_edittable.xhp">编辑数据透视表</topic>
|
||||
<topic id="scalc/text/scalc/guide/datapilot_filtertable.xhp">筛选数据透视表</topic>
|
||||
<topic id="scalc/text/scalc/guide/datapilot_tipps.xhp">选择数据透视表输出范围</topic>
|
||||
<topic id="scalc/text/scalc/guide/datapilot_updatetable.xhp">更新数据透视表</topic>
|
||||
</node>
|
||||
<node id="0810" title="方案">
|
||||
<topic id="scalc/text/scalc/guide/scenario.xhp">使用方案</topic>
|
||||
</node>
|
||||
<node id="0811" title="引用">
|
||||
<topic id="scalc/text/scalc/guide/relativ_absolut_ref.xhp">地址和引用,绝对和相对</topic>
|
||||
<topic id="scalc/text/scalc/guide/cellreferences.xhp">引用其他文档中的单元格</topic>
|
||||
<topic id="scalc/text/scalc/guide/cellreferences_url.xhp">引用其他工作表和参考 URL</topic>
|
||||
<topic id="scalc/text/scalc/guide/cellreference_dragdrop.xhp">通过拖放来引用单元格</topic>
|
||||
<topic id="scalc/text/scalc/guide/address_auto.xhp">寻址时识别名称</topic>
|
||||
</node>
|
||||
<node id="0812" title="查看、选择和复制">
|
||||
<topic id="scalc/text/scalc/guide/table_view.xhp">修改表格视图</topic>
|
||||
<topic id="scalc/text/scalc/guide/formula_value.xhp">显示公式或数值</topic>
|
||||
<topic id="scalc/text/scalc/guide/line_fix.xhp">行或列作为标题固定</topic>
|
||||
<topic id="scalc/text/scalc/guide/multi_tables.xhp">浏览工作表标签</topic>
|
||||
<topic id="scalc/text/scalc/guide/edit_multitables.xhp">复制到多个工作表</topic>
|
||||
<topic id="scalc/text/scalc/guide/cellcopy.xhp">仅复制可见单元格</topic>
|
||||
<topic id="scalc/text/scalc/guide/mark_cells.xhp">选择多个单元格</topic>
|
||||
</node>
|
||||
<node id="0813" title="公式和计算">
|
||||
<topic id="scalc/text/scalc/guide/formulas.xhp">通过公式计算</topic>
|
||||
<topic id="scalc/text/scalc/guide/formula_copy.xhp">复制公式</topic>
|
||||
<topic id="scalc/text/scalc/guide/formula_enter.xhp">输入公式</topic>
|
||||
<topic id="scalc/text/scalc/guide/formula_value.xhp">显示公式或数值</topic>
|
||||
<topic id="scalc/text/scalc/guide/calculate.xhp">电子表格中的计算</topic>
|
||||
<topic id="scalc/text/scalc/guide/calc_date.xhp">使用日期和时间进行计算</topic>
|
||||
<topic id="scalc/text/scalc/guide/calc_series.xhp">自动计算序列</topic>
|
||||
<topic id="scalc/text/scalc/guide/calc_timevalues.xhp">计算时差</topic>
|
||||
<topic id="scalc/text/scalc/guide/matrixformula.xhp">输入矩阵公式</topic>
|
||||
</node>
|
||||
<node id="0814" title="保护">
|
||||
<topic id="scalc/text/scalc/guide/cell_protect.xhp">保护单元格不被修改</topic>
|
||||
<topic id="scalc/text/scalc/guide/cell_unprotect.xhp">取消单元格保护</topic>
|
||||
</node>
|
||||
<node id="0815" title="其他">
|
||||
<!-- removed scalc/text/scalc/guide/autofill.xhp -->
|
||||
<topic id="scalc/text/scalc/guide/auto_off.xhp">停用自动修改</topic>
|
||||
<topic id="scalc/text/scalc/guide/consolidate.xhp">合并计算数据</topic>
|
||||
<topic id="scalc/text/scalc/guide/goalseek.xhp">应用单变量求解</topic>
|
||||
<topic id="scalc/text/scalc/guide/multioperation.xhp">应用多重计算</topic>
|
||||
<topic id="scalc/text/scalc/guide/multitables.xhp">应用多个工作表</topic>
|
||||
<topic id="scalc/text/scalc/guide/validity.xhp">单元格内容的有效性</topic>
|
||||
</node>
|
||||
</help_section>
|
||||
</tree_view>
|
@ -0,0 +1,30 @@
|
||||
###############################################################
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
###############################################################
|
||||
|
||||
Title=%PRODUCTNAME Chart
|
||||
|
||||
Language=zh-CN
|
||||
Order=4
|
||||
Start=text%2Fschart%2Fmain0000.xhp
|
||||
Heading=headingheading
|
||||
Program=CHART
|
||||
07.07.04 00:00:00
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--***********************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***********************************************************-->
|
||||
<tree_view version="24-Aug-2004">
|
||||
<help_section application="scalc" id="05" title="图表和图解">
|
||||
<node id="0501" title="一般信息">
|
||||
<topic id="schart/text/schart/main0000.xhp">%PRODUCTNAME 中的图表</topic>
|
||||
<topic id="schart/text/schart/main0503.xhp">%PRODUCTNAME 图表功能</topic>
|
||||
<topic id="schart/text/schart/04/01020000.xhp">图表的快捷键</topic>
|
||||
</node>
|
||||
</help_section>
|
||||
</tree_view>
|
@ -0,0 +1,30 @@
|
||||
###############################################################
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
###############################################################
|
||||
|
||||
|
||||
Title=%PRODUCTNAME Base
|
||||
|
||||
Language=zh-CN
|
||||
Order=7
|
||||
Start=text%2Fshared%2Fexplorer%2Fdatabase%2Fmain.xhp
|
||||
Heading=headingheading
|
||||
Program=DATABASE
|
||||
07.07.04 00:00:00
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue