The macro below, first requests the location of the library and the
destination folder. Next a new addon file is being created by help of the
"Package" service. The "Package" service also provides an
"XSingleServiceFactory" interface to create file and folder objects. To
navigate trough the addon files structure a "XHierarchicalNameAccess"
interface is used. Once the right path object has been retrieved use its
"XNameContainer" interface to add the file objects to the addon file.
To copy the content of a file to the file object use its "XActiveDataSink"
interface and provide the file by opening the file with the
"SimpleFileAccess" service. To make the folder a library, change the
folders "MediaType" property to the apropriate string.
For further details see http://wi.wu-wien.ac.at/rgf/diplomarbeiten/BakkStuff/2008/200809_Frysak/200809_Frysak_Automating_OOo_ooRexx_Nutshells.pdf.
-- try to get a script context, will be .nil, if script was not invoked by OOo
x_ScriptContext = uno.getScriptContext()
if (x_ScriptContext <> .nil) then
do
-- invoked by OOo as a macro
-- get context
x_ComponentContext = x_ScriptContext~getComponentContext
-- get desktop (an XDesktop)
x_Desktop = x_ScriptContext~getDesktop
-- get current document
x_Document = x_ScriptContext~getDocument
end
else
do
-- called from outside of OOo, create a connection
-- connect to Open Office and get component context
x_ComponentContext = UNO.connect()
-- create a desktop service and its interface
service = "{%see com.sun.star.frame.Desktop}"
s_Desktop = x_ComponentContext~getServiceManager~{%see com.sun.star.lang.XMultiServiceFactory%XMultiServiceFactory}~createInstance(service)
x_Desktop = s_Desktop~{%see com.sun.star.frame.XDesktop%XDesktop}
-- get the last active document
x_Document = x_Desktop~getCurrentComponent()
end
-- first we will ask for the foldername name of the library using the folder dialog
x_MultiServiceFactory = x_ComponentContext~getServiceManager()~{%see com.sun.star.lang.XMultiServiceFactory%XMultiServiceFactory}
folderpicker = "{%see com.sun.star.ui.dialogs.OfficeFolderPicker}"
s_FolderDialog = x_MultiServiceFactory~createInstance(folderpicker)
x_FolderDialog = s_FolderDialog~{%see com.sun.star.ui.dialogs.XFolderPicker%XFolderPicker}
-- better name for our dialog:
x_FolderDialog~setDescription("Select User Library to Export")
-- get Path to user Macros
s_pathsubst = x_MultiServiceFactory~createInstance("{%see com.sun.star.util.PathSubstitution}")
x_stringsubst = s_pathsubst~{%see com.sun.star.util.XStringSubstitution%XStringSubstitution}
usermacropath = x_stringsubst~getSubstituteVariableValue("$(user)") || "/Scripts/oorexx"
-- set Directory of Dialog to user macro directory
x_FolderDialog~setDisplayDirectory(usermacropath)
-- start the folder dialog
pathchoosen = x_FolderDialog~execute()
if ( pathchoosen ) then
do
-- if ok button pressed:
-- read selected path
librarypath = x_FolderDialog~getDirectory()
-- create file access interface to access files
s_SimpleFileAccess = x_MultiServiceFactory~createInstance("{%see com.sun.star.ucb.SimpleFileAccess}")
x_SimpleFileAccess = s_SimpleFileAccess~{%see com.sun.star.ucb.XSimpleFileAccess%XSimpleFileAccess}
-- check if parcel-descriptorfile can be found in library directory
islibrary = x_SimpleFileAccess~exists(librarypath || "/parcel-descriptor.xml")
if (islibrary) then
do
-- if parcel deskriptor- file can be found:
-- use Folder Picker again to get destination folder
x_FolderDialog~setDescription("Select Export destination")
if ( x_FolderDialog~execute() ) then
do
-- if OK-button pressed:
-- generate package filename with pathname
libraryname = getLastFromURL(librarypath)
savefile = x_FolderDialog~getDirectory() || "/" || libraryname || ".oxt"
-- if the file already exists, delete it
delete = SysFileDelete(uno.convertFromURL(savefile))
if (delete > 2) then
do
-- check for file deletion errors (32 = file is blocked by other thread)
errortext = "File delete error: " || delete || ", accessed by other thread?"
.bsf.dialog~messageBox(errortext, "ERROR", "error")
exit 0
end
-- now create package object
s_Package = x_MultiServiceFactory~createInstance("{%see com.sun.star.packages.Package}")
x_PackageInit = s_Package~{%see com.sun.star.lang.XInitialization%XInitialization}
-- initialize the package
c_String = .bsf4rexx~Class.class~forName("java.lang.String")
initargs = .bsf~bsf.createArray(c_String, 1)
initargs[1] = savefile
x_PackageInit~initialize(initargs)
-- get access to the directory structure of the zip file
x_HierarchicalNameAccess = s_Package~{%see com.sun.star.container.XHierarchicalNameAccess%XHierarchicalNameAccess}
-- get the root item and its containerinterface
o_RootPackageStream = x_HierarchicalNameAccess~getByHierarchicalName("")
x_RootNameContainer = o_RootPackageStream~{%see com.sun.star.container.XNameContainer%XNameContainer}
-- now create a factory which is able to create new subdirectories and files
x_PackageFactory = s_Package~{%see com.sun.star.lang.XSingleServiceFactory%XSingleServiceFactory}
-- arguments to create a directory
-- arguments MUST BE OBJECTS not primitive types!
.bsf~bsf.import("java.lang.Boolean", "c_Boolean")
dirargs = .bsf~bsf.createArray(.c_Boolean, 1)
dirargs[1] = .c_Boolean~new("true")
s_PackageFolder = x_PackageFactory~createInstanceWithArguments(dirargs)
-- insert directory object into package
x_RootNameContainer~insertByName(libraryname, s_PackageFolder)
-- go into the new created directory and query a container interface for it
o_LibraryPackageStream = x_HierarchicalNameAccess~getByHierarchicalName(libraryname)
x_LibraryNameContainer = o_LibraryPackageStream~{%see com.sun.star.container.XNameContainer%XNameContainer}
-- make this directory an ooRexx script library
x_LibraryPropertySet = o_LibraryPackageStream~{%see com.sun.star.beans.XPropertySet%XPropertySet}
scripttype = "application/vnd.sun.star.framework-script;type=ooRexx"
x_LibraryPropertySet~setPropertyValue("MediaType", scripttype)
-- set arguments to create a file
fileargs = .bsf~bsf.createArray(.c_Boolean, 1)
fileargs[1] = .c_Boolean~new("false")
-- get all files within librarypath
libraryfiles = x_SimpleFileAccess~getFolderContents(librarypath, 0)
-- go trough all files and add them to the package directory
libraryfileslength = libraryfiles~items
do counter = 1 to libraryfileslength
-- first create a fileobject and get the datasink interface of it
o_FilePackageStream = x_PackageFactory~createInstanceWithArguments(fileargs)
x_ActiveDataSink = o_FilePackageStream~{%see com.sun.star.io.XActiveDataSink%XActiveDataSink}
-- next open a file and get its inputstream
x_InputStream = x_SimpleFileAccess~openFileRead(libraryfiles[counter])
-- tell the datasink where to read the data from
-- this starts the reading process
x_ActiveDataSink~SetInputStream(x_InputStream)
-- now insert the filled file object to the package
filename = getLastFromURL(libraryfiles[counter])
x_LibraryNameContainer~insertByName(filename, o_FilePackageStream)
end
/*
Here we write a file directly into the zip file.
To do so we first create a new subdirectory and enter it.
Next a pipeobject is created, this allows sending data from
an outputinterface to an inputinterface. Now we create a
Textoutputstream and write data in it. Finally we use a
Datasink object like the one before to read the data and
store it in the created file.
*/
s_InfoPackageFolder = x_PackageFactory~createInstanceWithArguments(dirargs)
x_RootNameContainer~insertByName("PACKAGEINFO", s_InfoPackageFolder)
s_InfoPipe = x_MultiServiceFactory~createInstance("{%see com.sun.star.io.Pipe}")
x_InfoPipeOutputStream = s_InfoPipe~{%see com.sun.star.io.XOutputStream%XOutputStream}
x_InfoPipeInputStream = s_InfoPipe~{%see com.sun.star.io.XInputStream%XInputStream}
textstream = "{%see com.sun.star.io.TextOutputStream}"
s_InfoTextOutputStream = x_MultiServiceFactory~createInstance(textstream)
x_InfoActiveDataSource = s_InfoTextOutputStream~{%see com.sun.star.io.XActiveDataSource%XActiveDataSource}
x_InfoActiveDataSource~setOutputStream(x_InfoPipeOutputStream)
x_InfoTextOutputStream = s_InfoTextOutputStream~{%see com.sun.star.io.XTextOutputStream%XTextOutputStream}
-- clear stream
x_InfoPipeOutputStream~flush()
crlf = "0d"x || "0a"x
texttowrite = 'This Package was created by ExportLibrary macro by Josef Frysak' || crlf
texttowrite = texttowrite || 'on ' || DATE("L") || ' at ' || TIME("C")
x_InfoTextOutputStream~writeString(texttowrite)
-- write into stream
x_InfoPipeOutputStream~closeOutput()
o_InfoPackageStream = x_HierarchicalNameAccess~getByHierarchicalName("PACKAGEINFO")
x_InfoNameContainer = o_InfoPackageStream~{%see com.sun.star.container.XNameContainer%XNameContainer}
o_InfoFileStream = x_PackageFactory~createInstanceWithArguments(fileargs)
x_InfoActiveDataSink = o_InfoFileStream~{%see com.sun.star.io.XActiveDataSink%XActiveDataSink}
x_InfoActiveDataSink~SetInputStream(x_InfoPipeInputStream)
x_InfoNameContainer~insertByName("info.txt", o_InfoFileStream)
-- if all changes are done, we write the data to the zipfile
x_ChangesBatch = s_Package~{%see com.sun.star.util.XChangesBatch%XChangesBatch}
x_ChangesBatch~commitChanges()
end
end
else
do
-- a message in case the selected library is not containing
-- a parcel-descriptor file
errortext = "Selected Directory is not a Library: no parcel-descriptor found "
.bsf.dialog~messageBox(errortext, "ERROR", "error")
end
end
-- a simple routine to parse the name of the file or the directory name
getLastFromURL:
use arg url
return RIGHT(url, LENGTH(url) - LASTPOS("/", url))
::requires UNO.CLS