这里直接给出链接地址: http://wiki.openoffice.org/wiki/JavaEclipseTuto
需要注意的是,如果是Linux下,启动eclipse之前,需要先运行setsdkenv_unix(在sdk目录下)来设定环境,否则的话
会出现一些莫名其妙的问题。
这里直接给出链接地址: http://wiki.openoffice.org/wiki/JavaEclipseTuto
需要注意的是,如果是Linux下,启动eclipse之前,需要先运行setsdkenv_unix(在sdk目录下)来设定环境,否则的话
会出现一些莫名其妙的问题。
只需要将以下参数加入到OO的preference中就可以了。
-Xdebug
-Xnoagent
-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000(jvm会等待) 或者
-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000(jvm不会等待)
http://wiki.openoffice.org/wiki/Java
然后在eclipse中建立一个Remote Java Application launch config,端口好是8000,就可以了。
1. install open office
2.1 in eclipse create a user library: openoffice point to following jars
juh.jar jurt.jar ridl.jar java_uno.jar unoloader.jar unoil.jar
2.2 in eclipse create a OO_PROGRAM variable point to soffice location
3. create a java project, add openoffice library, OO_PROGRAM to this project
classpath
3.1 create a UNO java file
for example:
FirstUnoContact.java
package org.openoffice.test;
public class FirstUnoContact {
public static void main(String[] args) {
try {
// get the remote office component context
com.sun.star.uno.XComponentContext xContext = com.sun.star.comp.helper.Bootstrap.bootstrap();
System.out.println("Connected to a running office ...");
com.sun.star.lang.XMultiComponentFactory xMCF = xContext.getServiceManager();
String available = (xMCF != null ? "available" : "not available");
System.out.println("remote ServiceManager is " + available);
} catch (java.lang.Exception e) {
e.printStackTrace();
} finally {
System.exit(0);
}
}
}
4. run it
如果OO是启动的话,输出可能是如下结果:
Connected to a running office …
remote ServiceManager is available
http://wiki.openoffice.org/wiki/Documentation/DevGuide/FirstSteps/Configuration
The root object for connections to OpenOffice.org (and to any UNO application)
the service manager. The root object serves as the entry point for every UNO
application and is passed to every UNO component during instantiation.
用来链接到OO的源对象是service manager,这个对象是任何UNO应用程序的入口,并且任何一个UNO对象都可以访问到它。
The com.sun.star.lang.ServiceManager is the main factory in every UNO
application. It instantiates services by their service name, to enumerate all
implementations of a certain service, and to add or remove factories for a
certain service at runtime. The service manager is passed to every UNO
component during instantiation.
com.sun.star.lang.ServiceManager是任何UNO程序的主工厂,它根据服务名来实例化services,枚举一个服务所实现的interface,在运行时来追加或者移除某个服务的
工厂类。在每个UNO组件实例化的过程中service manager都会被传入。
UNO objects in different environments connect via the interprocess bridge. You
can execute calls on UNO object instances, that are located in a different
process.
This is done by converting the method name and the arguments into a byte
stream representation, and sending this package to the remote process, for
example, through a socket connection.
UNO对象在不同的环境中通过进程间的桥的完成通信的,你可以在一个进程中来调用另外一个进程的UNO对象,这是通过将方法名和参数转换成字节流,然后打包发送给远端进程来实现的,比如通过socket来发送字节流,或者命名管道。
下面是我通过ethereal抓取的包:
0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 …………..E.
0010 00 9c db 37 40 00 40 06 61 22 7f 00 00 01 7f 00 ...7@.@.a”……
0020 00 01 ce 2e 27 0f a0 42 a2 86 ea 67 cb d8 80 18 ….’..B…g….
0030 00 81 fe 90 00 00 01 01 08 0a 06 c3 79 b3 06 c3 …………y…
0040 79 b0 00 00 00 60 00 00 00 01 f8 04 96 00 00 27 y….`………’
0050 63 6f 6d 2e 73 75 6e 2e 73 74 61 72 2e 62 72 69 com.sun.star.bri
0060 64 67 65 2e 58 50 72 6f 74 6f 63 6f 6c 50 72 6f dge.XProtocolPro
0070 70 65 72 74 69 65 73 15 55 72 70 50 72 6f 74 6f perties.UrpProto
0080 63 6f 6c 50 72 6f 70 65 72 74 69 65 73 00 00 14 colProperties…
0090 04 00 00 00 66 7f ad 6e ee e6 4f e3 b5 68 90 df ….f..n..O..h..
00a0 ca 81 1e be 00 00 b3 4f 00 9b …….O..
Block header:
1. size 00 00 00 60 表示数据包的大小,不包含数据包的头,大小是0x60
2. message count 00 00 00 01 表示message的个数是1
Message 1
3. flag:f8 表示:
const sal_uInt8 HDRFLAG_LONGHEADER = 0x80;
const sal_uInt8 HDRFLAG_REQUEST = 0x40;
const sal_uInt8 HDRFLAG_NEWTYPE = 0x20;
const sal_uInt8 HDRFLAG_NEWOID = 0x10;
const sal_uInt8 HDRFLAG_NEWTID = 0x08;
4. 04 表示method id是04
5. nTypeClass: 96
nCacheIndex 00 00
com.sun.star.bridge.XProtocolProperties.UrpProtocolProperties 发送的是URP数据。
我是通过分析OO的code得出前5部的含义的,具体source可参见bridges/source/remote/urp/*
但是后面的感觉不对,所以没有写出来,希望有人能写一个ethereal的插件来完成这个分析工作就好了。
you can got the details about URP from
http://wiki.openoffice.org/wiki/Uno/Remote/Specifications/Uno_Remote_Protocol
UNO (Universal Network Objects)
The goal of UNO (Universal Network Objects) is to provide an environment for
network objects across programming language and platform boundaries.
UNO objects run and communicate everywhere. UNO reaches this goal by providing
the following fundamental framework:
UNO的目的是为网络对象提供跨平台和跨语言的运行环境,UNO对象可以在任何地方运行和通信。UNO是通过以下的基础框架来实现这个目的的:
1. UNO objects are specified in an abstract meta language, called UNOIDL (UNO
Interface Definition Language), which is similar to CORBA IDL or MIDL.
UNO对象是用UNOIDL语言来描述的,它和CORBA的IDL或者MIDL相似。
From UNOIDL specifications, language dependent header files and libraries can
be generated to implement UNO objects in the target language.
通过UNOIDL,与语言无关的头文件和库可以被生成,然后用对应的语言来实现。
UNO objects in the form of compiled and bound libraries are called components.
Components must support certain base interfaces to be able to run in the UNO
environment.
组件是UNO对象和帮助库的集合,组件必须实现一些interface,这样才能在UNO环境中执行。
2. To instantiate components in a target environment UNO uses a factory
concept.
工厂概念被用来在UNO环境中实例化组件。
This factory is called the service manager. It maintains a database of
registered components which are known by their name and can be created by
name.
这个工厂就是service manager。它来维护一个已经注册了的组件的数据库,用来通过组件名获得组件,或者用组件名来创建组件。
The service manager might ask Linux to load and instantiate a shared object
written in C++ or it might call upon the local Java VM to instantiate a Java
class.
service manager有可能或让linux来加载和实例化共享对象(C++实现),或者使用本地java虚拟机来初始化java对象。
This is transparent for the developer, there is no need to care about a
component’s implementation language. Communication takes place exclusively
over interface calls as specified in UNOIDL.
这个过程对开发人员是透明的,开发人员不需要关注组件的实现语言。通信是通过interface互斥的情况下来调用的。
3. UNO provides bridges to send method calls and receive return values
between processes and between objects written in different implementation
languages.
UNO通过bridge在不同的进程,不同的实现语言的对象之间,来发送方法调用,获得返回值。
The remote bridges use a special UNO remote protocol (URP) for this purpose
which is supported for sockets and pipes.
远程桥是通过UNO的URP协议来完成这个工作的(sockets 或者pipes )。
Both ends of the bridge must be UNO environments, therefore a language-
specific UNO runtime environment to connect to another UNO process in any of
the supported languages is required.
桥的两端必须是UNO环境,所以一个特定语言实现的UNO环境连接到另外一个UNO环境(所以所支持的语言)是必须的,
These runtime environments are provided as language bindings.
这些运行时环境是通过语言绑定来实现的。
4. Most objects of OpenOffice.org are able to communicate in a UNO
environment. The specification for the programmable features of OpenOffice.org
is called the OpenOffice.org API.
大部分的OpenOffice.org对象都是可以在UNO环境中通信的。OpenOffice.org
API.是用来通过给程序员来操作OpenOffice.org的接口。
具体的code请参见: http://blog.csdn.net/lantianjialiang/article/details/7971327
只不过有两步需要修改:
bison -y -d parser.l –> bison -y -d -t parser.l
gcc y.tab.o lex.yy.o -o plusmins.exe –>gcc -g lex.yy.o y.tab.o -o
plusminis.exe
以下是debug的屏幕输出:
gdb plusminis.exe
…
Breakpoint 1, main () at parser.l:30
30 yyparse();
(gdb) set yydebug=1 // 使debug生效,也可以将 yydebug=1 放到main函数中去
(gdb) cont
Continuing.
Starting parse
Entering state 0 //进入状态0
Reducing stack by rule 2 (line 14):
$$ = nterm program ()
Stack now 0
Entering state 1 //进入状态1
Reading a token: 3 //等待用户输入,输入是3
Next token is token INTEGER ()
Shifting token INTEGER () //压栈
Entering state 3 //进入状态3
Reducing stack by rule 3 (line 18):
$1 = token INTEGER ()
- > $$ = nterm expr () //根据rule 3 expr: INTEGER,将INTEGER替换成expr
Stack now 0 1 //替换完成后,栈中的状态是0,1
Entering state 4 //进入状态4
Reading a token: Next token is token ‘\n’ ()
Shifting token ‘\n’ ()
Entering state 5 //进入状态5, 栈中的状态是0,1,4,
Reducing stack by rule 1 (line 13):
$1 = nterm program ()
$2 = nterm expr ()
$3 = token ‘\n’ ()
3
- > $$ = nterm program () //根据rule 1 program: program expr ‘\n’,将 program
expr ‘\n ‘替换成program,同时输出expr
Stack now 0
Entering state 1
-—————————
Reading a token: 3+3
Next token is token INTEGER ()
Shifting token INTEGER ()
Entering state 3
Reducing stack by rule 3 (line 18):
$1 = token INTEGER ()
-> $$ = nterm expr ()
Stack now 0 1
Entering state 4
Reading a token: Next token is token ‘+’ ()
Shifting token ‘+’ ()
Entering state 6
Reading a token: Next token is token INTEGER ()
Shifting token INTEGER ()
Entering state 3
Reducing stack by rule 3 (line 18):
$1 = token INTEGER ()
-> $$ = nterm expr ()
Stack now 0 1 4 6 //这里其实是状态机中的状态的入栈情况
Entering state 8
Reading a token: Next token is token ‘\n’ ()
Reducing stack by rule 4 (line 19):
$1 = nterm expr ()
$2 = token ‘+’ ()
$3 = nterm expr ()
$$ = nterm expr () //根据rule 4 expr ‘+’ expr { $$ = $1 + $3; },会更新栈顶的expr值
Stack now 0 1
Entering state 4
Next token is token ‘\n’ ()
Shifting token ‘\n’ ()
Entering state 5
Reducing stack by rule 1 (line 13):
$1 = nterm program ()
$2 = nterm expr ()
$3 = token ‘\n’ ()
6
-> $$ = nterm program ()
Stack now 0
Entering state 1
-————————
Reading a token: s
invalid character
Next token is token ‘\n’ ()
syntax error
Error: popping nterm program ()
Stack now 0
Cleanup: discarding lookahead token ‘\n’ ()
Stack now 0
Program exited normally.
(gdb) quit
使用bison -y -d -t -v parser.l产生的状态机parser.output
State 8 conflicts: 2 shift/reduce
State 9 conflicts: 2 shift/reduce
Grammar
0 $accept: program $end
1 program: program expr '\n'
2 | /* empty */
3 expr: INTEGER
4 | expr '+' expr
5 | expr '-' expr
Terminals, with rules where they appear
$end (0) 0
'\n' (10) 1
'+' (43) 4
'-' (45) 5
error (256)
INTEGER (258) 3
Nonterminals, with rules where they appear
$accept (7)
on left: 0
program (8)
on left: 1 2, on right: 0 1
expr (9)
on left: 3 4 5, on right: 1 4 5
state 0
0 $accept: . program $end
$default reduce using rule 2 (program)
program go to state 1
state 1
0 $accept: program . $end
1 program: program . expr '\n'
$end shift, and go to state 2
INTEGER shift, and go to state 3
expr go to state 4
state 2
0 $accept: program $end .
$default accept
state 3
3 expr: INTEGER .
$default reduce using rule 3 (expr)
state 4
1 program: program expr . '\n'
4 expr: expr . '+' expr
5 | expr . '-' expr
'\n' shift, and go to state 5
'+' shift, and go to state 6
'-' shift, and go to state 7
state 5
1 program: program expr '\n' .
$default reduce using rule 1 (program)
state 6
4 expr: expr '+' . expr
INTEGER shift, and go to state 3
expr go to state 8
state 7
5 expr: expr '-' . expr
INTEGER shift, and go to state 3
expr go to state 9
state 8
4 expr: expr . '+' expr
4 | expr '+' expr .
5 | expr . '-' expr
'+' shift, and go to state 6
'-' shift, and go to state 7
'+' [reduce using rule 4 (expr)]
'-' [reduce using rule 4 (expr)]
$default reduce using rule 4 (expr)
state 9
4 expr: expr . '+' expr
5 | expr . '-' expr
5 | expr '-' expr .
'+' shift, and go to state 6
'-' shift, and go to state 7
'+' [reduce using rule 5 (expr)]
'-' [reduce using rule 5 (expr)]
$default reduce using rule 5 (expr)
refs: http://www.gnu.org/software/bison/manual/html_node/Understanding.html
parser.l:
%{
#include <stdio.h>
int yylex(void);
void yyerror(char *);
%}
%token INTEGER
%%
program:
program expr '\n' { printf("%d\n", $2); }
|
;
expr:
INTEGER { $$ = $1; }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
;
%%
void yyerror(char *s) {
fprintf(stderr, "%s\n", s);
}
int main(void) {
yyparse();
return 0;
}
scanner.l
%{
#include "y.tab.h"
#include <stdlib.h>
void yyerror(char *);
%}
%%
[0-9]+ {
yylval = atoi(yytext);
return INTEGER;
}
[-+\n] return *yytext;
[ \t] ; /* skip whitespace */
. yyerror("invalid character");
%%
这个编译器实现简单的加减,不支持括号。
编译:
bison -y -d parser.l
flex scanner.l
gcc -c y.tab.c lex.yy.c
gcc y.tab.o lex.yy.o -o plusmins.exe
以下是运行例:
[jialiang@host tmp]$ ./plusminis.exe
2+3
5
3+3+3-1
8
d
invalid character
syntax error