summaryrefslogtreecommitdiff
path: root/src/org/libreoffice/tools/types/TypeManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/libreoffice/tools/types/TypeManager.java')
-rw-r--r--src/org/libreoffice/tools/types/TypeManager.java301
1 files changed, 301 insertions, 0 deletions
diff --git a/src/org/libreoffice/tools/types/TypeManager.java b/src/org/libreoffice/tools/types/TypeManager.java
new file mode 100644
index 0000000..355d755
--- /dev/null
+++ b/src/org/libreoffice/tools/types/TypeManager.java
@@ -0,0 +1,301 @@
+package org.libreoffice.tools.types;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.apache.commons.cli.CommandLine;
+
+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.XInterfaceAttributeTypeDescription2;
+import com.sun.star.reflection.XPropertyTypeDescription;
+import com.sun.star.reflection.XTypeDescription;
+import com.sun.star.registry.XSimpleRegistry;
+import com.sun.star.uno.RuntimeException;
+import com.sun.star.uno.TypeClass;
+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 {
+
+ public static final String NOPROPERTYHELPER = "_";
+
+ 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 );
+ }
+
+ public void checkType( String pTypeName, ArrayList<String> pServices, ArrayList<String> pInterfaces,
+ ArrayList< XPropertyTypeDescription > pMembers ) {
+ try {
+ XTypeDescription descr = searchType( pTypeName );
+
+ switch ( descr.getTypeClass().getValue() ) {
+ case TypeClass.INTERFACE_value:
+ // Don't add the css.lang.XTypeProvider and cxx.uno.XWeak
+ if ( !pTypeName.equals( "com.sun.star.lang.XTypeProvider" ) &&
+ !pTypeName.equals( "com.sun.star.uno.XWeak" ) &&
+ !pInterfaces.contains( pTypeName ) ) {
+ pInterfaces.add( pTypeName );
+ }
+ break;
+ case TypeClass.SERVICE_value:
+ if ( !pServices.contains( pTypeName ) ) {
+ pServices.add( pTypeName );
+
+ Service service = new Service( descr );
+ if ( service.getSupertype() != null ) {
+ // New style services
+
+ String supertype = service.getSupertype().getName();
+ if ( !pInterfaces.contains( supertype ) ) {
+ pInterfaces.add( supertype );
+ }
+
+ // check if constructors are specified, if yes automatically
+ // support of XInitialization. We will take care of the default
+ // constructor because in this case XInitialization is not called.
+ if ( service.getMethodCount() > 1 ||
+ service.getMethodCount() == 1 && service.getMethodName( 0 ).length() > 0 ) {
+ String initIterface = "com.sun.star.lang.XInitialization";
+ if ( !pInterfaces.contains( initIterface ) ) {
+ pInterfaces.add( initIterface );
+ }
+ }
+ } else {
+ // Old style services
+
+ for ( int i = 0, len = service.getReferenceCount(); i < len; i++ ) {
+ String refName = service.getReferenceTypeName( i );
+ checkType( refName, pServices, pInterfaces, pMembers );
+ }
+
+ // Get the properties
+ for ( int i = 0, len = service.getPropertiesCount(); i < len; i++ ) {
+ pMembers.add( service.getProperty( i ) );
+ }
+ }
+ }
+ break;
+ }
+ } catch ( Exception e ) {
+ }
+ }
+
+ public String checkPropertyHelper(CommandLine pArgs, ArrayList<String> pServices, ArrayList<String> pInterfaces,
+ ArrayList<XInterfaceAttributeTypeDescription2> pAttributes, ArrayList<String> pPropinterfaces) {
+
+ String result = new String();
+
+ Iterator<String> it = pInterfaces.iterator();
+ if ( !pServices.isEmpty() ) {
+ it = pServices.iterator();
+ }
+
+ boolean oldStyleWithProps = false;
+ boolean propMixin = Boolean.parseBoolean( pArgs.getOptionValue( "propertysetmixin" ) );
+ while ( it.hasNext() && result.isEmpty() ) {
+ String typename = it.next( );
+ try {
+ XTypeDescription typeDesc = searchType( typename );
+ if ( !pServices.isEmpty() ) {
+ Service service = new Service( typeDesc );
+
+ if ( propMixin && service.getSupertype() != null ) {
+ Interface iface = new Interface( service.getSupertype() );
+ iface.checkAttributes( pAttributes, pPropinterfaces );
+
+ if ( !pAttributes.isEmpty() && !pPropinterfaces.isEmpty() ) {
+ result = service.getSupertype().getName();
+ }
+ } else {
+ oldStyleWithProps = service.hasProperties();
+ }
+ } else {
+ Interface iface = new Interface( typeDesc );
+ iface.checkAttributes( pAttributes, pPropinterfaces );
+ if ( !pAttributes.isEmpty() && !pPropinterfaces.isEmpty() ) {
+ result = typename;
+ }
+ }
+ } catch( Exception e ) {
+ }
+ }
+
+ if ( result.isEmpty() && oldStyleWithProps ) {
+ result = NOPROPERTYHELPER;
+ }
+
+ return result;
+ }
+
+ public boolean checkXComponentSupport( ArrayList<String> pInterfaces ) {
+
+ boolean supported = false;
+
+ if ( pInterfaces.isEmpty() ) {
+ supported = false;
+ } else {
+
+ Iterator<String> it = pInterfaces.iterator();
+ while ( it.hasNext() && !supported ) {
+ String typeName = it.next( );
+ if ( typeName.equals( "com.sun.star.lang.XComponent" ) ) {
+ pInterfaces.remove( "com.sun.star.lang.XComponent" );
+ supported = true;
+ } else {
+ try {
+ XTypeDescription descr = searchType( typeName );
+ Interface iface = new Interface( descr );
+ supported = iface.checkXComponentSupport( );
+ } catch ( NoSuchElementException e ) {
+ }
+ }
+ }
+ }
+
+ return supported;
+ }
+
+ /**
+ * 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" );
+ File basisDir = getPortableLink( installDir, "basis-link" );
+ File ureDir = getPortableLink( basisDir, "ure-link" );
+
+ URL[] urls = new URL[] {
+ programDir.toURI().toURL(),
+ new File( ureDir, "lib" ).toURI().toURL(),
+ new File( ureDir, "share/java" ).toURI().toURL(),
+ new File( basisDir, "program" ).toURI().toURL(),
+ new File( basisDir, "program/classes" ).toURI().toURL()
+ };
+
+ URLClassLoader loader = new URLClassLoader( urls );
+ mCtxt = Bootstrap.bootstrap( loader );
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 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.
+ *
+ * @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 File getPortableLink( File pParent, String pName ) {
+ File link = null;
+
+ File linkFile = new File( pParent, pName );
+ if ( System.getProperty( "os.name" ).toLowerCase().indexOf( "win" ) >= 0 ) {
+ // 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;
+ }
+
+ 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();
+ }
+ }
+}