summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCédric Bosdonnat <cedricbosdo@openoffice.org>2009-10-20 22:10:31 +0200
committerCédric Bosdonnat <cedricbosdo@openoffice.org>2009-10-20 22:10:31 +0200
commite7fe8ec8d3fda1589364fc2bffb773161e3232b7 (patch)
tree31a7e1643163656d5c961c59ad306d04b6d8973c
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
-rw-r--r--.classpath13
-rw-r--r--.gitignore1
-rw-r--r--.project17
-rw-r--r--.settings/org.eclipse.jdt.core.prefs84
-rw-r--r--.settings/org.eclipse.jdt.ui.prefs6
-rw-r--r--langs/cpp/lang.properties1
-rw-r--r--langs/java4/lang.properties1
-rw-r--r--langs/java5/lang.properties1
-rw-r--r--libs/commons-cli-1.2/LICENSE.txt202
-rw-r--r--libs/commons-cli-1.2/commons-cli-1.2-javadoc.jarbin0 -> 214274 bytes
-rw-r--r--libs/commons-cli-1.2/commons-cli-1.2-sources.jarbin0 -> 48726 bytes
-rw-r--r--libs/commons-cli-1.2/commons-cli-1.2.jarbin0 -> 41123 bytes
-rw-r--r--src/org/openoffice/tools/LanguageHelper.java63
-rw-r--r--src/org/openoffice/tools/OptionsHelper.java60
-rw-r--r--src/org/openoffice/tools/SkeletonMaker.java76
-rw-r--r--src/org/openoffice/tools/options/Command.java80
-rw-r--r--src/org/openoffice/tools/options/HelpFormatter.java111
-rw-r--r--src/org/openoffice/tools/options/SubCommand.java28
-rw-r--r--src/org/openoffice/tools/options/SubcommandLine.java24
-rw-r--r--src/org/openoffice/tools/tests/AllTests.java14
-rw-r--r--src/org/openoffice/tools/tests/CommandTest.java134
-rw-r--r--src/org/openoffice/tools/tests/LanguageHelperTest.java47
-rw-r--r--src/org/openoffice/tools/tests/TypeManagerTest.java120
-rw-r--r--src/org/openoffice/tools/types/Bootstrap.java337
-rw-r--r--src/org/openoffice/tools/types/TypeManager.java115
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
new file mode 100644
index 0000000..1677c89
--- /dev/null
+++ b/libs/commons-cli-1.2/commons-cli-1.2-javadoc.jar
Binary files differ
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
new file mode 100644
index 0000000..80b9c14
--- /dev/null
+++ b/libs/commons-cli-1.2/commons-cli-1.2-sources.jar
Binary files differ
diff --git a/libs/commons-cli-1.2/commons-cli-1.2.jar b/libs/commons-cli-1.2/commons-cli-1.2.jar
new file mode 100644
index 0000000..ce4b9ff
--- /dev/null
+++ b/libs/commons-cli-1.2/commons-cli-1.2.jar
Binary files differ
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();
+ }
+ }
+}