diff options
author | Cédric Bosdonnat <cedricbosdo@openoffice.org> | 2009-10-20 22:10:31 +0200 |
---|---|---|
committer | Cédric Bosdonnat <cedricbosdo@openoffice.org> | 2009-10-20 22:10:31 +0200 |
commit | e7fe8ec8d3fda1589364fc2bffb773161e3232b7 (patch) | |
tree | 31a7e1643163656d5c961c59ad306d04b6d8973c |
Start a new uno-skeletonmaker
Currently implemented:
* the options are normally printed (thought not all set)
* the command line is properly parsed
* the type manager can be initialized and used to search types
descriptions
* the language data structure has been started: the language list
and their description for the options can be fetched.
Next important steps:
* Implement the component sub-command
25 files changed, 1535 insertions, 0 deletions
diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..5de4cc2 --- /dev/null +++ b/.classpath @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> + <classpathentry kind="lib" path="libs/commons-cli-1.2/commons-cli-1.2.jar" sourcepath="libs/commons-cli-1.2/commons-cli-1.2-sources.jar"> + <attributes> + <attribute name="javadoc_location" value="jar:platform:/resource/Skeletonmaker/libs/commons-cli-1.2/commons-cli-1.2-javadoc.jar!/"/> + </attributes> + </classpathentry> + <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/> + <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/OOo Classes"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba077a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bin diff --git a/.project b/.project new file mode 100644 index 0000000..32c6830 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>Skeletonmaker</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..f4b37e6 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,84 @@ +#Mon Oct 19 11:47:32 CEST 2009 +eclipse.preferences.version=1 +org.eclipse.jdt.core.codeComplete.argumentPrefixes=p +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes=m +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=s +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000..cd01d8b --- /dev/null +++ b/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,6 @@ +#Mon Oct 19 10:28:08 CEST 2009 +eclipse.preferences.version=1 +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=true +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.overrideannotation=true diff --git a/langs/cpp/lang.properties b/langs/cpp/lang.properties new file mode 100644 index 0000000..4b0c5ed --- /dev/null +++ b/langs/cpp/lang.properties @@ -0,0 +1 @@ +description = generate output for C++
\ No newline at end of file diff --git a/langs/java4/lang.properties b/langs/java4/lang.properties new file mode 100644 index 0000000..485031c --- /dev/null +++ b/langs/java4/lang.properties @@ -0,0 +1 @@ +description = generate output for Java 1.4 or earlier
\ No newline at end of file diff --git a/langs/java5/lang.properties b/langs/java5/lang.properties new file mode 100644 index 0000000..11ce36d --- /dev/null +++ b/langs/java5/lang.properties @@ -0,0 +1 @@ +description = generate output for Java 1.5 or later
\ No newline at end of file diff --git a/libs/commons-cli-1.2/LICENSE.txt b/libs/commons-cli-1.2/LICENSE.txt new file mode 100644 index 0000000..57bc88a --- /dev/null +++ b/libs/commons-cli-1.2/LICENSE.txt @@ -0,0 +1,202 @@ + 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. + diff --git a/libs/commons-cli-1.2/commons-cli-1.2-javadoc.jar b/libs/commons-cli-1.2/commons-cli-1.2-javadoc.jar Binary files differnew file mode 100644 index 0000000..1677c89 --- /dev/null +++ b/libs/commons-cli-1.2/commons-cli-1.2-javadoc.jar diff --git a/libs/commons-cli-1.2/commons-cli-1.2-sources.jar b/libs/commons-cli-1.2/commons-cli-1.2-sources.jar Binary files differnew file mode 100644 index 0000000..80b9c14 --- /dev/null +++ b/libs/commons-cli-1.2/commons-cli-1.2-sources.jar diff --git a/libs/commons-cli-1.2/commons-cli-1.2.jar b/libs/commons-cli-1.2/commons-cli-1.2.jar Binary files differnew file mode 100644 index 0000000..ce4b9ff --- /dev/null +++ b/libs/commons-cli-1.2/commons-cli-1.2.jar diff --git a/src/org/openoffice/tools/LanguageHelper.java b/src/org/openoffice/tools/LanguageHelper.java new file mode 100644 index 0000000..5a702d8 --- /dev/null +++ b/src/org/openoffice/tools/LanguageHelper.java @@ -0,0 +1,63 @@ +package org.openoffice.tools; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FilenameFilter; +import java.net.URISyntaxException; +import java.util.Properties; + +public class LanguageHelper { + + private static final String LANGS_DIR = "langs"; + private static final String DESCRIPTION_FILENAME = "lang.properties"; + + public static String[] getLanguages() { + File langsDir = getLangsDir(); + + String[] langs = langsDir.list( new FilenameFilter() { + + @Override + public boolean accept(File pDir, String pName) { + return !pName.startsWith("."); + } + }); + + return langs; + } + + public static String getDescription( String pLang ) { + String description = null; + File langsDir = getLangsDir(); + File langDir = new File( langsDir, pLang ); + + if ( langDir.isDirectory() ) { + File descFile = new File( langDir, DESCRIPTION_FILENAME ); + if ( descFile.isFile() && descFile.canRead() ) { + Properties props = new Properties( ); + FileInputStream in = null; + try { + in = new FileInputStream( descFile ); + props.load( in ); + description = props.getProperty( "description" ); + } catch ( Exception e ) { + } finally { + try { in.close(); } catch ( Exception e) { }; + } + } + } + + return description; + } + + private static File getLangsDir( ) { + File dir = null; + try { + File jarFile = new File(LanguageHelper.class.getProtectionDomain() + .getCodeSource().getLocation().toURI()); + dir = new File( jarFile.getParentFile(), LANGS_DIR ); + + } catch (URISyntaxException e) { + } + return dir; + } +} diff --git a/src/org/openoffice/tools/OptionsHelper.java b/src/org/openoffice/tools/OptionsHelper.java new file mode 100644 index 0000000..01633d2 --- /dev/null +++ b/src/org/openoffice/tools/OptionsHelper.java @@ -0,0 +1,60 @@ +package org.openoffice.tools; + +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionGroup; +import org.apache.commons.cli.Options; +import org.openoffice.tools.options.Command; +import org.openoffice.tools.options.SubCommand; + +/** + * Helper class generating the options list. + * + * @author cbosdonnat + * + */ +public class OptionsHelper { + + public static final String COMMAND_COMPONENT = "component"; + public static final String COMMAND_REGISTRATION = "registration"; + + // TODO Complete the arguments to handle here + protected static Command setupCommandLine( ) { + Command cmdLine = new Command(); + + // General options + Options generalOptions = new Options(); + + OptionGroup langGroup = new OptionGroup(); + String[] langs = LanguageHelper.getLanguages( ); + for (String lang : langs) { + Option langOpt = new Option( lang, false, LanguageHelper.getDescription( lang ) ); + langGroup.addOption( langOpt ); + } + langGroup.setRequired( true ); + generalOptions.addOptionGroup( langGroup ); + + generalOptions.addOption( "unoinstall", true, "url specifies a URL to an existing UNO environment (URE, office installation)." ); + generalOptions.addOption( "o", true, "path specifies an existing directory where the output files are generated to. If path=stdout the generated code is generated on standard out instead of a file." ); + + cmdLine.setCommonOptions( generalOptions ); + + // component command options + Options compOptions = new Options( ); + compOptions.addOption( "t", true, "specifies an UNOIDL type name, e.g. com.sun.star.text.XText" ); + compOptions.addOption( "l", true, "specifies a binary type library (can be used more than once). The type library is integrated as an additional type provider in the bootstrapped type system."); + compOptions.addOption( "n", true, "specifies an implementation name for the component (used as classname, filename and package|namespace name). In 'dump' mode it is used as classname (e.g. \"MyBase::\", C++ only) to generate method bodies not inline." ); + compOptions.addOption( "propertysetmixin", false, "the generated skeleton implements the cppu::PropertySetMixin helper if a referenced new style service specifies an interface which provides attributes (directly or inherited)." ); + SubCommand component = new SubCommand( COMMAND_COMPONENT, compOptions, + "generates language specific code skeleton files using the implementation name as the file and class name" ); + cmdLine.addCommand( component ); + + // registration options + Options regOptions = new Options(); + regOptions.addOption( "s", true, "name of the implementation of a service to add to the registration system." ); + SubCommand registration = new SubCommand( COMMAND_REGISTRATION, regOptions, + "creates the registration code for a list of services implementations. The '-s' option has to be used at least once to specify the implementation name of a service to add to the registration system." ); + cmdLine.addCommand( registration ); + + return cmdLine; + } +} diff --git a/src/org/openoffice/tools/SkeletonMaker.java b/src/org/openoffice/tools/SkeletonMaker.java new file mode 100644 index 0000000..5c77b8a --- /dev/null +++ b/src/org/openoffice/tools/SkeletonMaker.java @@ -0,0 +1,76 @@ +package org.openoffice.tools; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.ParseException; +import org.apache.commons.cli.PosixParser; +import org.openoffice.tools.options.Command; +import org.openoffice.tools.options.HelpFormatter; +import org.openoffice.tools.options.SubcommandLine; +import org.openoffice.tools.types.TypeManager; + +public class SkeletonMaker { + + public void generateComponent( CommandLine pArgs ) { + + TypeManager manager = null; + + try { + // Get the language first + String lang = getLanguage( pArgs ); + + // Load the types manager + String inifile = pArgs.getOptionValue( "unoinstall" ); + manager = new TypeManager( inifile ); + manager.initRegistries( pArgs.getOptionValues( "l" ) ); + + // Check the types + String[] types = pArgs.getOptionValues( "t" ); + for (String type : types) { + // TODO Get the service, interfaces... from it + } + + } catch ( Exception e ) { + e.printStackTrace(); + } finally { + // Close the running OOo + if ( manager != null ) { + manager.dispose(); + } + } + } + + public static void main(String[] args) { + + Command cmd = OptionsHelper.setupCommandLine(); + try { + SubcommandLine commandline = cmd.parse( args, new PosixParser() ); + + // TODO Add the other commands + String subCommand = commandline.getSubcommand(); + if ( subCommand.equals( OptionsHelper.COMMAND_COMPONENT ) ) { + SkeletonMaker maker = new SkeletonMaker(); + maker.generateComponent( commandline.getCommandLine() ); + + } else if ( subCommand.equals( OptionsHelper.COMMAND_REGISTRATION ) ) { + // TODO implement + } + } catch (ParseException e) { + System.err.println( e.getMessage() ); + + HelpFormatter.printHelp( "uno-skeletonmaker", cmd ); + } + } + + private String getLanguage( CommandLine pArgs ) { + String[] langs = LanguageHelper.getLanguages(); + String lang = null; + int i = 0; + while ( lang == null && i < langs.length ) { + if ( pArgs.hasOption( langs[i] ) ) { + lang = langs[i]; + } + i++; + } + return lang; + } +} diff --git a/src/org/openoffice/tools/options/Command.java b/src/org/openoffice/tools/options/Command.java new file mode 100644 index 0000000..480ae90 --- /dev/null +++ b/src/org/openoffice/tools/options/Command.java @@ -0,0 +1,80 @@ +package org.openoffice.tools.options; + +import java.util.Collection; +import java.util.HashMap; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionGroup; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; + +public class Command { + + private HashMap< String, SubCommand > mCommands; + private Options mCommonOptions; + + public Command( ) { + mCommands = new HashMap<String, SubCommand>(); + } + + public void addCommand( SubCommand pCommand ) { + if ( !mCommands.containsKey( pCommand.getName() ) ) { + mCommands.put( pCommand.getName(), pCommand ); + } + } + + public void removeCommand( String pCommandName ) { + mCommands.remove( pCommandName ); + } + + public Collection< SubCommand > getCommands( ) { + return mCommands.values(); + } + + public void setCommonOptions( Options pOptions ) { + mCommonOptions = pOptions; + } + + public Options getCommonOptions( ) { + return mCommonOptions; + } + + public SubcommandLine parse( String[] pArguments, CommandLineParser pParser ) throws ParseException { + if ( pArguments.length < 1 ) { + throw new ParseException( "No sub-command" ); + } + String subcommand = pArguments[0]; + + // Compute the final options list: common + subcommand + Options allOptions = new Options(); + addAllOptions( allOptions, mCommonOptions ); + + SubCommand def = mCommands.get( subcommand ); + if ( def == null ) { + throw new ParseException( "Invalid sub-command: " + subcommand ); + } + + addAllOptions( allOptions, def.getOptions() ); + + // Get only the subcommand arguments + String[] subCommandArguments = new String[ pArguments.length - 1 ]; + System.arraycopy( pArguments, 1, subCommandArguments, 0, subCommandArguments.length ); + + // Parse + CommandLine cmdline = pParser.parse( allOptions, subCommandArguments ); + + return new SubcommandLine( subcommand, cmdline ); + } + + private void addAllOptions(Options pAllOptions, Options pCommonOptions) { + for ( Object opt : pCommonOptions.getOptions() ) { + if ( opt instanceof Option ) { + pAllOptions.addOption( ( Option ) opt ); + } else if ( opt instanceof OptionGroup ) { + pAllOptions.addOptionGroup( (OptionGroup ) opt ); + } + } + } +} diff --git a/src/org/openoffice/tools/options/HelpFormatter.java b/src/org/openoffice/tools/options/HelpFormatter.java new file mode 100644 index 0000000..d61ea0d --- /dev/null +++ b/src/org/openoffice/tools/options/HelpFormatter.java @@ -0,0 +1,111 @@ +package org.openoffice.tools.options; + +import java.io.PrintStream; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Collection; + +public class HelpFormatter { + + private static final int TAB_SPACES = 4; + private static final int COMMAND_SEP_SPACES = 2; + + public static void printHelp( String pProgram, Command pCommandLine ) { + printHelp( System.out, 80, pProgram, pCommandLine ); + } + + public static void printHelp( PrintStream pOut, int pMaxLength, String pProgram, Command pCommandLine ) { + + org.apache.commons.cli.HelpFormatter formatter = new org.apache.commons.cli.HelpFormatter(); + formatter.setSyntaxPrefix( getFilledString( ' ', TAB_SPACES ) ); + PrintWriter pw = new PrintWriter( pOut ); + + // Output the global usage + pOut.println( "\nUsage:" ); + for ( SubCommand command : pCommandLine.getCommands() ) { + String app = pProgram + " " + command.getName(); + formatter.printUsage( pw, pMaxLength, app, command.getOptions() ); + } + pw.flush(); + + // Output the commands list + pOut.println( "\nSub-commands:" ); + printSubCommands( pOut, pMaxLength, pCommandLine.getCommands() ); + + + // Output the common options + pOut.println( "\nCommon options:" ); + formatter.printOptions( pw, pMaxLength, pCommandLine.getCommonOptions(), TAB_SPACES, COMMAND_SEP_SPACES ); + pw.flush(); + + + // Output the commands options + pOut.println( "\nSub-commands options:" ); + for ( SubCommand command : pCommandLine.getCommands() ) { + int nbOptions = command.getOptions().getOptions().size(); + if ( nbOptions > 0 ) { + pOut.println( getFilledString( ' ', TAB_SPACES ) + command.getName() ); + formatter.printOptions( pw, pMaxLength, command.getOptions(), TAB_SPACES * 2, COMMAND_SEP_SPACES ); + pw.flush(); + } + } + } + + private static void printSubCommands( PrintStream pOut, int pMaxLength, Collection<SubCommand> pCommands ) { + int maxCmdLength = 0; + for ( SubCommand command : pCommands ) { + if ( command.getName().length() > maxCmdLength ) { + maxCmdLength = command.getName().length(); + } + } + + for ( SubCommand command : pCommands ) { + String name = command.getName(); + String message = getFilledString( ' ', TAB_SPACES ) + name; + + int nameDiff = ( maxCmdLength - name.length() ); + message += getFilledString( ' ', nameDiff + COMMAND_SEP_SPACES ); + + int restLen = pMaxLength - maxCmdLength - TAB_SPACES - COMMAND_SEP_SPACES; + String aligningBlanks = getFilledString( ' ', pMaxLength - restLen ); + + String[] words = command.getDescription().split( " " ); + int i = 0; + boolean firstLine = true; + String line = new String(); + while ( i < words.length ) { + String word = words[i]; + if ( line.length() + 1 + word.length() < restLen ) { + if ( line.length() > 0 ) { + line += " "; + } + line += word; + + if ( i == words.length - 1 ) { + if ( !firstLine ) { + message += aligningBlanks; + } + message += line + "\n"; + } + + } else { + if ( !firstLine ) { + message += aligningBlanks; + } + message += line + "\n"; + line = word; + firstLine = false; + } + i++; + } + + pOut.print( message ); + } + } + + private static String getFilledString(char pChar, int pNumber) { + char[] chars = new char[pNumber]; + Arrays.fill( chars, pChar ); + return new String( chars ); + } +} diff --git a/src/org/openoffice/tools/options/SubCommand.java b/src/org/openoffice/tools/options/SubCommand.java new file mode 100644 index 0000000..c3aacd4 --- /dev/null +++ b/src/org/openoffice/tools/options/SubCommand.java @@ -0,0 +1,28 @@ +package org.openoffice.tools.options; + +import org.apache.commons.cli.Options; + +public class SubCommand { + + private String mName; + private String mDescription; + private Options mOptions; + + public SubCommand( String pName, Options pOptions, String pDescription ) { + mName = pName; + mDescription = pDescription; + mOptions = pOptions; + } + + public String getName() { + return mName; + } + + public String getDescription() { + return mDescription; + } + + public Options getOptions() { + return mOptions; + } +} diff --git a/src/org/openoffice/tools/options/SubcommandLine.java b/src/org/openoffice/tools/options/SubcommandLine.java new file mode 100644 index 0000000..2a6f716 --- /dev/null +++ b/src/org/openoffice/tools/options/SubcommandLine.java @@ -0,0 +1,24 @@ +package org.openoffice.tools.options; + +import org.apache.commons.cli.CommandLine; + +public class SubcommandLine { + + private static final long serialVersionUID = 1578591361018635215L; + + private String mSubcommand; + private CommandLine mCommandLine; + + public SubcommandLine( String pSubcommand, CommandLine pCommandLine ) { + mSubcommand = pSubcommand; + mCommandLine = pCommandLine; + } + + public String getSubcommand() { + return mSubcommand; + } + + public CommandLine getCommandLine() { + return mCommandLine; + } +} diff --git a/src/org/openoffice/tools/tests/AllTests.java b/src/org/openoffice/tools/tests/AllTests.java new file mode 100644 index 0000000..eacc661 --- /dev/null +++ b/src/org/openoffice/tools/tests/AllTests.java @@ -0,0 +1,14 @@ +package org.openoffice.tools.tests; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith( Suite.class ) +@SuiteClasses( { + LanguageHelperTest.class, + CommandTest.class, + TypeManagerTest.class } ) +public class AllTests { + +} diff --git a/src/org/openoffice/tools/tests/CommandTest.java b/src/org/openoffice/tools/tests/CommandTest.java new file mode 100644 index 0000000..06f4315 --- /dev/null +++ b/src/org/openoffice/tools/tests/CommandTest.java @@ -0,0 +1,134 @@ +package org.openoffice.tools.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionGroup; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.cli.PosixParser; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.openoffice.tools.options.Command; +import org.openoffice.tools.options.SubCommand; +import org.openoffice.tools.options.SubcommandLine; + +public class CommandTest { + + private Command mCommand; + + @Before + public void setUp() throws Exception { + mCommand = setupCommandLine(); + } + + @After + public void tearDown( ) throws Exception { + mCommand = null; + } + + @Test + public void testParseValid() { + String[] validArgs = new String[] { + "registration", + "-cpp", + "-s", + "TestImpl" + }; + + try { + SubcommandLine line = mCommand.parse( validArgs, new PosixParser() ); + assertNotNull( "Result of parsing is null", line.getCommandLine() ); + assertEquals( "Wrong subcommand", "registration", line.getSubcommand() ); + + // Check the presence of the last option and its value + assertTrue( "Option not recognized", line.getCommandLine().hasOption( "s" ) ); + assertEquals( "wrong value detected", "TestImpl", line.getCommandLine().getOptionValue( "s" ) ) ; + } catch (ParseException e) { + fail( "Unexcepted exception: " + e.getMessage() ); + } + } + + @Test + public void testParseSubcommandNameError() { + String[] validArgs = new String[] { + "failure", + "-cpp", + "-s", + "TestImpl" + }; + + try { + mCommand.parse( validArgs, new PosixParser() ); + fail( "Should have thrown an exception" ); + } catch (ParseException e) { + assertTrue( "Wrong exception message", e.getMessage().endsWith( "failure" ) ); + } + } + + @Test + public void testParseSubcommandArgsError() { + String[] validArgs = new String[] { + "registration", + "-cpp", + "--error", + "--err2" + }; + + try { + mCommand.parse( validArgs, new PosixParser() ); + fail( "Should have thrown an exception" ); + } catch (ParseException e) { + assertTrue( "Error message doesn't contain '--error'" , e.getMessage().contains( "--error" ) ); + } + } + + @Test( expected=ParseException.class ) + public void testParseSubcommandNoArg() throws Exception { + String[] validArgs = new String[] { + "uno-skeletonmaker" + }; + + mCommand.parse( validArgs, new PosixParser() ); + } + + private static Command setupCommandLine( ) { + Command cmdLine = new Command(); + + // General options + Options generalOptions = new Options(); + + OptionGroup langGroup = new OptionGroup(); + Option java5 = new Option( "java5", false, "generate output for Java 1.5 or later (is currently the default)" ); + Option java4 = new Option( "java4", false, "generate output for Java 1.4 or earlier" ); + Option cpp = new Option( "cpp", false, "generate output for C++" ); + langGroup.addOption( java4 ); + langGroup.addOption( java5 ); + langGroup.addOption( cpp ); + langGroup.setRequired( false ); + generalOptions.addOptionGroup( langGroup ); + + cmdLine.setCommonOptions( generalOptions ); + + + // component command options + Options compOptions = new Options( ); + compOptions.addOption( "t", true, "specifies an UNOIDL type name, e.g. com.sun.star.text.XText" ); + SubCommand component = new SubCommand( "component", compOptions, + "generates language specific code skeleton files using the implementation name as the file and class name" ); + cmdLine.addCommand( component ); + + // registration options + Options regOptions = new Options(); + regOptions.addOption( "s", true, "name of the implementation of a service to add to the registration system." ); + SubCommand registration = new SubCommand( "registration", regOptions, + "creates the registration code for a list of services implementations. The '-s' option has to be used at least once to specify the implementation name of a service to add to the registration system." ); + cmdLine.addCommand( registration ); + + return cmdLine; + } +} diff --git a/src/org/openoffice/tools/tests/LanguageHelperTest.java b/src/org/openoffice/tools/tests/LanguageHelperTest.java new file mode 100644 index 0000000..f6e0597 --- /dev/null +++ b/src/org/openoffice/tools/tests/LanguageHelperTest.java @@ -0,0 +1,47 @@ +package org.openoffice.tools.tests; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.Arrays; + +import org.junit.Test; +import org.openoffice.tools.LanguageHelper; + +/** + * ATM, the fixture of this class is the main language configuration: it + * would be more complex to generate the fixture here. + * + * @author cbosdonnat + * + */ +public class LanguageHelperTest { + + private static final String LANG = "cpp"; + private static final Object DESCRIPTION = "generate output for C++"; + + private static final String ERR_LANG = "err"; + + @Test + public void testGetLanguages( ) { + String[] result = LanguageHelper.getLanguages(); + String[] expected = new String[] { "cpp", "java4", "java5" }; + + // The order in results aren't guaranteed + Arrays.sort( result ); + assertArrayEquals( "Different values", expected, result ); + } + + @Test + public void testGetDescriptionOk( ) { + String actual = LanguageHelper.getDescription( LANG ); + assertEquals( DESCRIPTION , actual ); + } + + @Test + public void testGetDescriptionError( ) { + String actual = LanguageHelper.getDescription( ERR_LANG ); + assertNull( actual ); + } +} diff --git a/src/org/openoffice/tools/tests/TypeManagerTest.java b/src/org/openoffice/tools/tests/TypeManagerTest.java new file mode 100644 index 0000000..2037c02 --- /dev/null +++ b/src/org/openoffice/tools/tests/TypeManagerTest.java @@ -0,0 +1,120 @@ +package org.openoffice.tools.tests; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.openoffice.tools.types.TypeManager; + +import com.sun.star.container.NoSuchElementException; +import com.sun.star.reflection.XTypeDescription; + +/** + * This test class assumes a <code>ooo.install.dir</code> Java property is set and + * points to the directory of an installed OOo 3.x. + * + * @author cbosdonnat + * + */ +public class TypeManagerTest { + + private static final String SEARCHED_TYPE = "com.sun.star.lang.XTypeProvider"; + private static final String SEARCHED_TYPE_ERR = "some.dummy.type"; + + private static TypeManager sTestedManager; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + String installDir = System.getProperty( "ooo.install.dir" ); + + sTestedManager = new TypeManager( installDir ); + sTestedManager.initRegistries( new String[]{ + getUreRegistryUrl( installDir ) + } ); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + sTestedManager.dispose(); + } + + @Test + public void testSearchTypeValid() { + try { + XTypeDescription result = sTestedManager.searchType( SEARCHED_TYPE ); + assertEquals( "Actual description doesn't match", SEARCHED_TYPE, result.getName() ); + } catch ( NoSuchElementException e ) { + fail( "This element should be found" ); + } + } + + @Test( expected=NoSuchElementException.class ) + public void testSearchTypeIncorrect() throws Exception { + sTestedManager.searchType( SEARCHED_TYPE_ERR ); + } + + private static String getUreRegistryUrl( String pInstallDir ) { + String regUrl = null; + + try { + File install = new File( pInstallDir ); + File basis = getPortableLink( "basis-link", install ); + File ure = getPortableLink( "ure-link", basis ); + + String sep = System.getProperty( "file.separator" ); + File reg = new File( ure, "share" + sep + "misc" + sep + "types.rdb" ); + + if ( reg.canRead() ) { + regUrl = "file://" + reg.toURI().toURL().getPath(); + } + + } catch ( Exception e ) { + } + + return regUrl; + } + + /** + * Get the file object for the link defined as a child of a folder. + * + * On Windows platform, the link relative location is specified as the content of + * a file named after the link name. On Unix-based systems symbolic links are + * supported. + * + * <p>This method has been adapted from the ooeclipse integration code, class + * <code>org.openoffice.ide.eclipse.core.OOo.OOo3PathMapper</code></p> + * + * @param pName the name of the symbolic link + * @param pParent the parent directory file + * + * @return the file representing the link target or <code>null</code> + * + */ + private static File getPortableLink(String pName, File pParent) { + File link = null; + + File linkFile = new File(pParent, pName); + if ( System.getProperty( "os.name" ).toLowerCase().startsWith( "win" ) ) { + // Read the content of the file to get the true folder + try { + FileInputStream is = new FileInputStream(linkFile); + byte[] buf = new byte[is.available()]; + is.read(buf); + + String relativePath = new String(buf); + linkFile = new File(pParent, relativePath); + link = linkFile; + } catch (Exception e) { + // the returned link is null to show the error + } + } else { + link = linkFile; + } + + return link; + } +} diff --git a/src/org/openoffice/tools/types/Bootstrap.java b/src/org/openoffice/tools/types/Bootstrap.java new file mode 100644 index 0000000..d3bd3f4 --- /dev/null +++ b/src/org/openoffice/tools/types/Bootstrap.java @@ -0,0 +1,337 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: Bootstrap.java,v $ + * $Revision: 1.16 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package org.openoffice.tools.types; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.net.URLClassLoader; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Random; + +import com.sun.star.bridge.UnoUrlResolver; +import com.sun.star.bridge.XUnoUrlResolver; +import com.sun.star.comp.helper.BootstrapException; +import com.sun.star.comp.helper.ComponentContext; +import com.sun.star.comp.helper.ComponentContextEntry; +import com.sun.star.comp.loader.JavaLoader; +import com.sun.star.container.XSet; +import com.sun.star.lang.XInitialization; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XSingleComponentFactory; +import com.sun.star.lib.util.NativeLibraryLoader; +import com.sun.star.loader.XImplementationLoader; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; + +/** Bootstrap offers functionality to obtain a context or simply + a service manager. + The service manager can create a few basic services, whose implementations are: + <ul> + <li>com.sun.star.comp.loader.JavaLoader</li> + <li>com.sun.star.comp.urlresolver.UrlResolver</li> + <li>com.sun.star.comp.bridgefactory.BridgeFactory</li> + <li>com.sun.star.comp.connections.Connector</li> + <li>com.sun.star.comp.connections.Acceptor</li> + <li>com.sun.star.comp.servicemanager.ServiceManager</li> + </ul> + + Other services can be inserted into the service manager by + using its XSet interface: + <pre> + XSet xSet = (XSet)UnoRuntime.queryInterface( XSet.class, aMultiComponentFactory ); + // insert the service manager + xSet.insert( aSingleComponentFactory ); + </pre> + + @author cbosdo Changed the class for a better control of the bootstrap using a custom classloader +*/ +public class Bootstrap { + + private static void insertBasicFactories( + XSet xSet, XImplementationLoader xImpLoader ) + throws Exception + { + // insert the factory of the loader + xSet.insert( xImpLoader.activate( + "com.sun.star.comp.loader.JavaLoader", null, null, null ) ); + + // insert the factory of the URLResolver + xSet.insert( xImpLoader.activate( + "com.sun.star.comp.urlresolver.UrlResolver", null, null, null ) ); + + // insert the bridgefactory + xSet.insert( xImpLoader.activate( + "com.sun.star.comp.bridgefactory.BridgeFactory", null, null, null ) ); + + // insert the connector + xSet.insert( xImpLoader.activate( + "com.sun.star.comp.connections.Connector", null, null, null ) ); + + // insert the acceptor + xSet.insert( xImpLoader.activate( + "com.sun.star.comp.connections.Acceptor", null, null, null ) ); + } + + /** Bootstraps an initial component context with service manager and basic + jurt components inserted. + @param context_entries the hash table contains mappings of entry names (type string) to + context entries (type class ComponentContextEntry). + @return a new context. + */ + static public XComponentContext createInitialComponentContext( Hashtable context_entries ) + throws Exception + { + XImplementationLoader xImpLoader = (XImplementationLoader)UnoRuntime.queryInterface( + XImplementationLoader.class, new JavaLoader() ); + + // Get the factory of the ServiceManager + XSingleComponentFactory smgr_fac = (XSingleComponentFactory)UnoRuntime.queryInterface( + XSingleComponentFactory.class, xImpLoader.activate( + "com.sun.star.comp.servicemanager.ServiceManager", null, null, null ) ); + + // Create an instance of the ServiceManager + XMultiComponentFactory xSMgr = (XMultiComponentFactory)UnoRuntime.queryInterface( + XMultiComponentFactory.class, smgr_fac.createInstanceWithContext( null ) ); + + // post init loader + XInitialization xInit = (XInitialization)UnoRuntime.queryInterface( + XInitialization.class, xImpLoader ); + Object[] args = new Object [] { xSMgr }; + xInit.initialize( args ); + + // initial component context + if (context_entries == null) + context_entries = new Hashtable( 1 ); + // add smgr + context_entries.put( + "/singletons/com.sun.star.lang.theServiceManager", + new ComponentContextEntry( null, xSMgr ) ); + // ... xxx todo: add standard entries + XComponentContext xContext = new ComponentContext( context_entries, null ); + + // post init smgr + xInit = (XInitialization)UnoRuntime.queryInterface( + XInitialization.class, xSMgr ); + args = new Object [] { null, xContext }; // no registry, default context + xInit.initialize( args ); + + XSet xSet = (XSet)UnoRuntime.queryInterface( XSet.class, xSMgr ); + // insert the service manager + xSet.insert( smgr_fac ); + // and basic jurt factories + insertBasicFactories( xSet, xImpLoader ); + + return xContext; + } + + /** + * Bootstraps a servicemanager with the jurt base components registered. + * <p> + * @return a freshly boostrapped service manager + * @see com.sun.star.lang.ServiceManager + */ + static public XMultiServiceFactory createSimpleServiceManager() throws Exception + { + return (XMultiServiceFactory)UnoRuntime.queryInterface( + XMultiServiceFactory.class, createInitialComponentContext( null ).getServiceManager() ); + } + + + /** Bootstraps the initial component context from a native UNO installation. + + @see cppuhelper/defaultBootstrap_InitialComponentContext() + */ + static public final XComponentContext defaultBootstrap_InitialComponentContext() + throws Exception + { + return defaultBootstrap_InitialComponentContext( null, null ); + } + /** Bootstraps the initial component context from a native UNO installation. + + @param ini_file + ini_file (may be null: uno.rc besides cppuhelper lib) + @param bootstrap_parameters + bootstrap parameters (maybe null) + + @see cppuhelper/defaultBootstrap_InitialComponentContext() + */ + static public final XComponentContext defaultBootstrap_InitialComponentContext( + String ini_file, Hashtable bootstrap_parameters ) + throws Exception + { + // jni convenience: easier to iterate over array than calling Hashtable + String pairs [] = null; + if (null != bootstrap_parameters) + { + pairs = new String [ 2 * bootstrap_parameters.size() ]; + Enumeration keys = bootstrap_parameters.keys(); + int n = 0; + while (keys.hasMoreElements()) + { + String name = (String)keys.nextElement(); + pairs[ n++ ] = name; + pairs[ n++ ] = (String)bootstrap_parameters.get( name ); + } + } + + if (! m_loaded_juh) + { + System.loadLibrary( "juh" ); + m_loaded_juh = true; + } + return (XComponentContext)UnoRuntime.queryInterface( + XComponentContext.class, + cppuhelper_bootstrap( + ini_file, pairs, Bootstrap.class.getClassLoader() ) ); + } + + static private boolean m_loaded_juh = false; + static private native Object cppuhelper_bootstrap( + String ini_file, String bootstrap_parameters [], ClassLoader loader ) + throws Exception; + + /** + * Bootstraps the component context from a UNO installation. + * + * @return a bootstrapped component context. + * + * @since UDK 3.1.0 + */ + public static final XComponentContext bootstrap(URLClassLoader loader) + throws BootstrapException { + + XComponentContext xContext = null; + + try { + // create default local component context + XComponentContext xLocalContext = + createInitialComponentContext( null ); + if ( xLocalContext == null ) + throw new BootstrapException( "no local component context!" ); + + // find office executable relative to this class's class loader + String sOffice = + System.getProperty( "os.name" ).startsWith( "Windows" ) ? + "soffice.exe" : "soffice"; + File fOffice = NativeLibraryLoader.getResource( loader, sOffice ); + if ( fOffice == null ) + throw new BootstrapException( "no office executable found!" ); + + // create random pipe name + String sPipeName = "uno" + + Long.toString( (new Random()).nextLong() & 0x7fffffffffffffffL ); + + // create call with arguments + String[] cmdArray = new String[7]; + cmdArray[0] = fOffice.getPath(); + cmdArray[1] = "-nologo"; + cmdArray[2] = "-nodefault"; + cmdArray[3] = "-norestore"; + cmdArray[4] = "-nocrashreport"; + cmdArray[5] = "-nolockcheck"; + cmdArray[6] = "-accept=pipe,name=" + sPipeName + ";urp;"; + + // start office process + Process p = Runtime.getRuntime().exec( cmdArray ); + pipe( p.getInputStream(), System.out, "CO> " ); + pipe( p.getErrorStream(), System.err, "CE> " ); + + // initial service manager + XMultiComponentFactory xLocalServiceManager = + xLocalContext.getServiceManager(); + if ( xLocalServiceManager == null ) + throw new BootstrapException( "no initial service manager!" ); + + // create a URL resolver + XUnoUrlResolver xUrlResolver = + UnoUrlResolver.create( xLocalContext ); + + // connection string + String sConnect = "uno:pipe,name=" + sPipeName + + ";urp;StarOffice.ComponentContext"; + + // wait until office is started + for (int i = 0;; ++i) { + try { + // try to connect to office + Object context = xUrlResolver.resolve( sConnect ); + xContext = (XComponentContext) UnoRuntime.queryInterface( + XComponentContext.class, context); + if ( xContext == null ) + throw new BootstrapException( "no component context!" ); + break; + } catch ( com.sun.star.connection.NoConnectException ex ) { + // Wait 500 ms, then try to connect again, but do not wait + // longer than 5 min (= 600 * 500 ms) total: + if (i == 600) { + throw new BootstrapException(ex.toString()); + } + Thread.sleep( 500 ); + } + } + } catch ( BootstrapException e ) { + throw e; + } catch ( java.lang.RuntimeException e ) { + throw e; + } catch ( java.lang.Exception e ) { + throw new BootstrapException( e ); + } + + return xContext; + } + + private static void pipe( + final InputStream in, final PrintStream out, final String prefix ) { + + new Thread( "Pipe: " + prefix) { + public void run() { + BufferedReader r = new BufferedReader( + new InputStreamReader( in ) ); + try { + for ( ; ; ) { + String s = r.readLine(); + if ( s == null ) { + break; + } + out.println( prefix + s ); + } + } catch ( java.io.IOException e ) { + e.printStackTrace( System.err ); + } + } + }.start(); + } +} diff --git a/src/org/openoffice/tools/types/TypeManager.java b/src/org/openoffice/tools/types/TypeManager.java new file mode 100644 index 0000000..e0a8b34 --- /dev/null +++ b/src/org/openoffice/tools/types/TypeManager.java @@ -0,0 +1,115 @@ +package org.openoffice.tools.types; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Vector; + +import com.sun.star.container.NoSuchElementException; +import com.sun.star.container.XHierarchicalNameAccess; +import com.sun.star.container.XSet; +import com.sun.star.frame.XDesktop; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.reflection.XTypeDescription; +import com.sun.star.registry.XSimpleRegistry; +import com.sun.star.uno.RuntimeException; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; + +/* + * TODO: + * + Load the registries + * + use the introspection API to extract the useful infos from the type + */ +public class TypeManager { + + private String mInstallDir; + private XComponentContext mCtxt; + private XHierarchicalNameAccess mTypeDescMngr; + + public TypeManager( String pInstallDir ) { + mInstallDir = pInstallDir; + connect( ); + } + + public void dispose( ) { + disconnect(); + } + + public void initRegistries( String[] pUrls ) throws Exception { + // Get the type description manager + Object o = mCtxt.getValueByName( "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ); + mTypeDescMngr = (XHierarchicalNameAccess)UnoRuntime.queryInterface( XHierarchicalNameAccess.class, o ); + + if ( mTypeDescMngr == null ) { + throw new RuntimeException( "Couldn't get the type description manager from OOo" ); + } + + // Get the service manager + XMultiComponentFactory xServiceMngr = mCtxt.getServiceManager(); + + // Open the registries + XSimpleRegistry[] regs = new XSimpleRegistry[ pUrls.length ]; + for ( int i = 0; i < pUrls.length; i++ ) { + String regUrl = pUrls[i]; + o = xServiceMngr.createInstanceWithContext( "com.sun.star.registry.SimpleRegistry", mCtxt ); + XSimpleRegistry reg = (XSimpleRegistry)UnoRuntime.queryInterface( XSimpleRegistry.class, o ); + reg.open( regUrl, true, false); + regs[i] = reg; + } + + // Fill the type description manager + o = xServiceMngr.createInstanceWithArgumentsAndContext( + "com.sun.star.reflection.TypeDescriptionProvider", regs, mCtxt ); + XHierarchicalNameAccess tdProvider = (XHierarchicalNameAccess)UnoRuntime.queryInterface( + XHierarchicalNameAccess.class, o ); + if ( tdProvider == null ) { + throw new RuntimeException( "Can't initialize the TypeDescriptionProvider" ); + } + + XSet mngrSet = (XSet)UnoRuntime.queryInterface( XSet.class, mTypeDescMngr ); + mngrSet.insert( tdProvider ); + } + + /** + * Search the description of a given UNO type in the registries. + * + * @param pTypeName the name of the type to look for, separated by '.' + * + * @return the type description + * + * @throws NoSuchElementException if no element is corresponding to the asked type. + */ + public XTypeDescription searchType( String pTypeName ) throws NoSuchElementException { + Object o = mTypeDescMngr.getByHierarchicalName( pTypeName ); + return (XTypeDescription)UnoRuntime.queryInterface( XTypeDescription.class, o ); + } + + private void connect( ) { + try { + File installDir = new File( mInstallDir ); + File programDir = new File( installDir, "program" ); + URLClassLoader loader = new URLClassLoader( new URL[] { programDir.toURI().toURL() }); + mCtxt = Bootstrap.bootstrap( loader ); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void disconnect( ) { + try { + if ( mCtxt != null ) { + // Only the uno test suite which started the office can stop it + XMultiComponentFactory xMngr = mCtxt.getServiceManager(); + Object oDesktop = xMngr.createInstanceWithContext("com.sun.star.frame.Desktop", mCtxt); + XDesktop xDesktop = (XDesktop)UnoRuntime.queryInterface(XDesktop.class, oDesktop); + + xDesktop.terminate(); + mCtxt = null; + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} |