diff options
Diffstat (limited to 'src/org/libreoffice/tools/types/TypeManager.java')
-rw-r--r-- | src/org/libreoffice/tools/types/TypeManager.java | 301 |
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(); + } + } +} |