Fix 57: Passive component registration (#152)

This commit is contained in:
prrvchr
2025-03-27 07:00:55 +01:00
committed by GitHub
parent 4b4ced368c
commit 9808cdfb0a
20 changed files with 1537 additions and 568 deletions

1
build/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
antbuild.sh

View File

@ -4,7 +4,7 @@
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/>
<classpathentry kind="src" path="source"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/LO-Classes"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
<attributes>
<attribute name="module" value="true"/>
</attributes>

View File

@ -21,7 +21,8 @@ Require-Bundle: org.eclipse.core.runtime;visibility:=reexport,
org.eclipse.ui.forms,
org.eclipse.debug.core;visibility:=reexport,
org.eclipse.debug.ui,
org.eclipse.ui
org.eclipse.ui,
org.eclipse.jdt.core
Export-Package: org.libreoffice.ide.eclipse.core,
org.libreoffice.ide.eclipse.core.actions,
org.libreoffice.ide.eclipse.core.builders,

View File

@ -94,7 +94,6 @@ public class TypesBuilder extends IncrementalProjectBuilder {
static int sBuildState = NOT_STARTED_STATE;
private static String sExtension = "idl";
private boolean mChangedIdl = false;
/**
@ -140,29 +139,26 @@ public class TypesBuilder extends IncrementalProjectBuilder {
@Override
public boolean visit(IResourceDelta delta) throws CoreException {
boolean visitChildren = false;
boolean visitChild = false;
IProject prj = getProject();
IUnoidlProject unoprj = ProjectsManager.getProject(prj.getName());
IUnoidlProject unoPrj = ProjectsManager.getProject(prj.getName());
if (unoprj != null) {
IPath idlPath = unoprj.getIdlPath();
IPath resPath = delta.getResource().getProjectRelativePath();
int resType = delta.getResource().getType();
if (unoPrj != null) {
IResource res = delta.getResource();
if (resType == IResource.PROJECT) {
visitChildren = true;
} else if (resType == IResource.FOLDER &&
resPath.toString().startsWith(idlPath.toString())) {
visitChildren = true;
} else if (resType == IResource.FILE) {
if (sExtension.equalsIgnoreCase(resPath.getFileExtension())) { //$NON-NLS-1$
if (res.getType() == IResource.PROJECT) {
visitChild = true;
} else if (res.getType() == IResource.FOLDER) {
visitChild = res.getProjectRelativePath().toString().startsWith(unoPrj.getIdlDir());
} else if (res.getType() == IResource.FILE) {
if (res.getFileExtension().equals(IUnoidlProject.IDL_EXTENSION)) {
mChangedIdl = true;
} else if (resPath.toString().endsWith(unoprj.getTypesPath().toString())) {
} else if (res.equals(unoPrj.getTypesFile())) {
sBuildState = COMPLETED_STATE;
}
}
}
return visitChildren;
return visitChild;
}
});
}
@ -203,6 +199,9 @@ public class TypesBuilder extends IncrementalProjectBuilder {
languageBuilder.generateFromTypes(unoprj.getSdk(), unoprj.getOOo(), prj, types,
build, unoprj.getRootModule(), monitor);
// Check manifest.xml types file entry
unoprj.checkManifestTypes();
prj.refreshLocal(IResource.DEPTH_INFINITE, monitor);
sBuildState = NOT_STARTED_STATE;
}

View File

@ -196,7 +196,7 @@ public class PackageContentSelector extends Composite {
pack.addContent(UnoPackage.getPathRelativeToBase(resFile, prjFile), resFile);
}
IFile componentFile = project.getFile(project.getName() + ".component");
IFile componentFile = project.getComponentsFile();
if (componentFile.exists()) {
File resFile = SystemHelper.getFile(componentFile);
pack.addContent(UnoPackage.getPathRelativeToBase(resFile, prjFile), resFile);

View File

@ -0,0 +1,266 @@
/*************************************************************************
* The Contents of this file are made available subject to the terms of
* the GNU Lesser General Public License Version 2.1
*
* Sun Microsystems Inc., October, 2000
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc..
*
* Copyright: 2002 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): Cedric Bosdonnat
*
*
************************************************************************/
package org.libreoffice.ide.eclipse.core.internal.helpers;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.TextEdit;
import org.libreoffice.ide.eclipse.core.PluginLogger;
import org.libreoffice.ide.eclipse.core.model.IUnoidlProject;
/**
* This class is an helper for modifying the skeleton produced by uno-skeletonmaker
* when it does not support passive registration.
*
*/
public final class UnoSkeletonHelper {
public static boolean supportPassiveRegistration(IUnoidlProject prj, String command, IProgressMonitor monitor) {
String version = "0.4"; //$NON-NLS-1$
Process process = prj.getSdk().runTool(prj, command + " --version", monitor); //$NON-NLS-1$
// To get uno-skeletonmaker version we need to process the error stream
try {
String error = readErrorStream(process);
version = error.substring(error.lastIndexOf(' ') + 1);
} catch (IOException e) { }
return version.compareTo("0.5") > -1; //$NON-NLS-1$
}
public static String readErrorStream(Process process) throws IOException {
String error = null;
try (InputStream input = process.getErrorStream();
Scanner scanner = new Scanner(input).useDelimiter("\\A")) { //$NON-NLS-1$
if (scanner.hasNext()) {
error = scanner.next().trim();
}
}
return error;
}
public static void cleanupJavaSkeleton(IFile file, String serviceName, IProgressMonitor monitor) {
try {
Document document = removeUnneededCode(file, monitor);
addNeededCode(document, serviceName, monitor);
// Save the document
Files.writeString(file.getLocation().toPath(), document.get());
} catch (MalformedTreeException | BadLocationException |
IOException | JavaModelException | IllegalArgumentException e) {
PluginLogger.error("UnoSkeletonHelper.cleanupJavaSkeleton ERROR", e); //$NON-NLS-1$
}
}
private static Document removeUnneededCode(IFile file, IProgressMonitor monitor)
throws MalformedTreeException, BadLocationException,
JavaModelException, IllegalArgumentException {
ICompilationUnit compilationUnit = JavaCore.createCompilationUnitFrom(file);
Document document = new Document(compilationUnit.getSource());
CompilationUnit unit = getCompilationUnit(compilationUnit, monitor);
ASTRewrite rewriter = ASTRewrite.create(unit.getAST());
// Remove all import except XComponentContext and WeakBase
for (ImportDeclaration imp : ImportDeclarationFinder.perform(unit)) {
rewriter.remove(imp, null);
}
// Remove all methods starting with "__"
for (MethodDeclaration method : MethodDeclarationFinder.perform(unit)) {
rewriter.remove(method, null);
}
// Apply changes
TextEdit edits = rewriter.rewriteAST();
edits.apply(document);
return document;
}
@SuppressWarnings("unchecked")
private static void addNeededCode(Document document, String serviceName, IProgressMonitor monitor)
throws MalformedTreeException, BadLocationException {
// Add m_serviceName field
CompilationUnit unit = getCompilationUnit(document.get(), monitor);
unit.recordModifications();
FieldDeclaration serviceNameField = getServiceNameField(unit.getAST(), serviceName);
int indexField = FieldIndexFinder.perform(unit);
TypeDeclaration type = (TypeDeclaration) unit.types().get(0);
type.bodyDeclarations().add(indexField, (BodyDeclaration) serviceNameField);
// Apply changes
TextEdit edits = unit.rewrite(document, null);
edits.apply(document);
}
private static CompilationUnit getCompilationUnit(ICompilationUnit unit, IProgressMonitor monitor) {
ASTParser parser = getParser();
parser.setResolveBindings(true);
parser.setBindingsRecovery(true);
parser.setSource(unit);
return (CompilationUnit) parser.createAST(monitor);
}
private static CompilationUnit getCompilationUnit(String source, IProgressMonitor monitor) {
ASTParser parser = getParser();
parser.setSource(source.toCharArray());
return (CompilationUnit) parser.createAST(monitor);
}
private static ASTParser getParser() {
ASTParser parser = ASTParser.newParser(AST.getJLSLatest());
parser.setKind(ASTParser.K_COMPILATION_UNIT);
return parser;
}
@SuppressWarnings("unchecked")
private static FieldDeclaration getServiceNameField(AST ast, String serviceName) {
VariableDeclarationFragment fragment = ast.newVariableDeclarationFragment();
StringLiteral literal = ast.newStringLiteral();
literal.setLiteralValue(serviceName);
fragment.setInitializer(literal);
fragment.setName(ast.newSimpleName("m_serviceName"));
FieldDeclaration fieldDeclaration = ast.newFieldDeclaration(fragment);
fieldDeclaration.setType(ast.newSimpleType(ast.newSimpleName("String")));
fieldDeclaration.modifiers().addAll(ast.newModifiers(Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL));
return fieldDeclaration;
}
private static final class MethodDeclarationFinder extends ASTVisitor {
private final List <MethodDeclaration> mMethods = new ArrayList <> ();
public static List<MethodDeclaration> perform(ASTNode node) {
MethodDeclarationFinder finder = new MethodDeclarationFinder();
node.accept(finder);
return finder.getMethods();
}
@Override
public boolean visit (final MethodDeclaration method) {
if (method.getName().getIdentifier().startsWith("__")) {
mMethods.add (method);
}
return super.visit(method);
}
/**
* @return an immutable list view of the methods discovered by this visitor
*/
public List <MethodDeclaration> getMethods() {
return Collections.unmodifiableList(mMethods);
}
}
private static final class ImportDeclarationFinder extends ASTVisitor {
private final List <ImportDeclaration> mImports = new ArrayList <> ();
public static List<ImportDeclaration> perform(ASTNode node) {
ImportDeclarationFinder finder = new ImportDeclarationFinder();
node.accept(finder);
return finder.getImports();
}
@Override
public boolean visit (final ImportDeclaration imp) {
String fullName = imp.getName().getFullyQualifiedName();
if (!(fullName.endsWith("XComponentContext") || fullName.endsWith("WeakBase"))) {
mImports.add (imp);
}
return super.visit(imp);
}
/**
* @return an immutable list view of the imports discovered by this visitor
*/
public List <ImportDeclaration> getImports() {
return Collections.unmodifiableList(mImports);
}
}
private static final class FieldIndexFinder extends ASTVisitor {
private int mCount = 0;
private int mIndex = 0;
public static int perform(ASTNode node) {
FieldIndexFinder finder = new FieldIndexFinder();
node.accept(finder);
return finder.getFieldIndex();
}
@Override
public boolean visit (final FieldDeclaration field) {
if (field.toString().contains("m_serviceNames")) {
mIndex = mCount;
}
mCount ++;
return super.visit(field);
}
/**
* @return index of m_serviceNames field discovered by this visitor
*/
public int getFieldIndex() {
return mIndex;
}
}
}

View File

@ -38,8 +38,7 @@ package org.libreoffice.ide.eclipse.core.internal.model;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
@ -49,6 +48,7 @@ import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.ui.IWorkbenchPage;
import org.libreoffice.ide.eclipse.core.PluginLogger;
import org.libreoffice.ide.eclipse.core.internal.helpers.UnoSkeletonHelper;
import org.libreoffice.ide.eclipse.core.internal.helpers.UnoidlProjectHelper;
import org.libreoffice.ide.eclipse.core.model.CompositeFactory;
import org.libreoffice.ide.eclipse.core.model.IUnoComposite;
@ -99,7 +99,7 @@ public final class UnoFactory {
out = new FileOutputStream(file);
descrModel.serialize(out);
} catch (Exception e) {
// TODO Log ?
// XXX: Log ?
} finally {
try {
out.close();
@ -148,96 +148,66 @@ public final class UnoFactory {
public static void makeSkeleton(UnoFactoryData data, IWorkbenchPage activePage, IProgressMonitor monitor)
throws Exception {
String prjName = (String) data.getProperty(IUnoFactoryConstants.PROJECT_NAME);
IUnoidlProject prj = ProjectsManager.getProject(prjName);
String serviceName = getSkeletonServiceName(data);
AbstractLanguage lang = (AbstractLanguage) data.getProperty(IUnoFactoryConstants.PROJECT_LANGUAGE);
IProjectHandler langProjectHandler = lang.getProjectHandler();
String languageOption = langProjectHandler.getSkeletonMakerLanguage(data);
if (languageOption != null) {
if (serviceName != null && languageOption != null) {
String prjName = (String) data.getProperty(IUnoFactoryConstants.PROJECT_NAME);
IUnoidlProject prj = ProjectsManager.getProject(prjName);
// Get the registries
String typesReg = ""; //$NON-NLS-1$
String[] oooTypes = prj.getOOo().getTypesPath();
for (String oooType : oooTypes) {
oooType = oooType.replace("\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$
oooType = oooType.replace(" ", "%20"); //$NON-NLS-1$ //$NON-NLS-2$
oooType = "file:///" + oooType; //$NON-NLS-1$
String command = prj.getSdk().getCommand("uno-skeletonmaker"); //$NON-NLS-1$
// We need to know if uno-skeletonmaker support passive registration
boolean passiveRegistration = UnoSkeletonHelper.supportPassiveRegistration(prj, command, monitor);
typesReg += " -l " + oooType; //$NON-NLS-1$
}
String prjTypes = prj.getTypesPath().toString();
typesReg += " -l " + prjTypes; //$NON-NLS-1$
// Get the service for which to generate the skeleton
UnoFactoryData[] inner = data.getInnerData();
String service = ""; //$NON-NLS-1$
int i = 0;
while (i < inner.length && service.equals("")) { //$NON-NLS-1$
int typeNature = ((Integer) inner[i].getProperty(IUnoFactoryConstants.TYPE_NATURE)).intValue();
if (typeNature == IUnoFactoryConstants.SERVICE) {
String name = (String) inner[i].getProperty(IUnoFactoryConstants.TYPE_NAME);
String module = (String) inner[i].getProperty(IUnoFactoryConstants.PACKAGE_NAME);
String fullname = module + "::" + name; //$NON-NLS-1$
fullname = fullname.replaceAll("::", "."); //$NON-NLS-1$ //$NON-NLS-2$
service = fullname;
}
i++;
}
String implementationName = langProjectHandler.getImplementationName(prj, service);
String typesReg = getSkeletonTypesRegistry(prj);
String implementationName = langProjectHandler.getImplementationName(prj, serviceName);
// Run the uno-skeletonmaker command
String command = prj.getSdk().getCommand("uno-skeletonmaker") + //$NON-NLS-1$
" component " + languageOption + //$NON-NLS-1$
" --propertysetmixin" + //$NON-NLS-1$
" -o ./" + prj.getSourcePath().toOSString() + //$NON-NLS-1$
command += " component " + languageOption + //$NON-NLS-1$
" --propertysetmixin"; //$NON-NLS-1$
if (passiveRegistration) {
command += " --passive-registration"; //$NON-NLS-1$
}
command += " -o ./" + prj.getSourcePath().toOSString() + //$NON-NLS-1$
" " + typesReg + //$NON-NLS-1$
" -n " + implementationName + //$NON-NLS-1$
" -t " + service; //$NON-NLS-1$
" -t " + serviceName; //$NON-NLS-1$
Process process = prj.getSdk().runTool(prj, command, monitor);
// Process the error output to add it to the log if needed
InputStream err = process.getErrorStream();
StringWriter writer = new StringWriter();
String error = null;
try {
int c = err.read();
while (c != -1) {
writer.write(c);
c = err.read();
}
} finally {
try {
err.close();
String error = writer.toString();
if (!error.equals("")) { //$NON-NLS-1$
PluginLogger.error(error);
} else {
PluginLogger.info(Messages.getString("UnoFactory.SkeletonGeneratedMessage") + //$NON-NLS-1$
implementationName);
}
} catch (java.io.IOException e) {
}
error = UnoSkeletonHelper.readErrorStream(process);
} catch (IOException e) {
error = e.getMessage();
}
if (error != null) {
if (error.isEmpty()) {
String msg = Messages.getString("UnoFactory.SkeletonGeneratedMessage"); //$NON-NLS-1$
PluginLogger.info(msg + implementationName);
} else {
PluginLogger.error(error);
}
} else {
IPath implementationPath = langProjectHandler.getImplementationFile(implementationName);
implementationPath = prj.getSourcePath().append(implementationPath);
IFile implementationFile = prj.getFile(implementationPath);
// Refresh the project to reflect the changes
UnoidlProjectHelper.refreshProject(prj, null);
// Refresh the project to reflect the changes
UnoidlProjectHelper.refreshProject(prj, null);
// opens the generated files
IPath implementationPath = langProjectHandler.getImplementationFile(implementationName);
implementationPath = prj.getSourcePath().append(implementationPath);
IFile implementationFile = prj.getFile(implementationPath);
// If passive registration is not supported we need to cleanup the generated Java skeleton code
if (!passiveRegistration) {
UnoSkeletonHelper.cleanupJavaSkeleton(implementationFile, serviceName, monitor);
}
WorkbenchHelper.showFile(implementationFile, activePage);
// Opens the generated files
WorkbenchHelper.showFile(implementationFile, activePage);
}
}
}
@ -554,4 +524,41 @@ public final class UnoFactory {
fileContent.addChild(CompositeFactory.createInclude(types[i]));
}
}
private static String getSkeletonServiceName(UnoFactoryData data) {
// Get the service for which to generate the skeleton
String service = null;
UnoFactoryData[] inner = data.getInnerData();
int i = 0;
while (i < inner.length && service == null) {
int typeNature = ((Integer) inner[i].getProperty(IUnoFactoryConstants.TYPE_NATURE)).intValue();
if (typeNature == IUnoFactoryConstants.SERVICE) {
String name = (String) inner[i].getProperty(IUnoFactoryConstants.TYPE_NAME);
String module = (String) inner[i].getProperty(IUnoFactoryConstants.PACKAGE_NAME);
String fullname = module + "::" + name; //$NON-NLS-1$
fullname = fullname.replaceAll("::", "."); //$NON-NLS-1$ //$NON-NLS-2$
service = fullname;
}
i++;
}
return service;
}
private static String getSkeletonTypesRegistry(IUnoidlProject prj) {
// Get the registries
String typesReg = ""; //$NON-NLS-1$
String[] oooTypes = prj.getOOo().getTypesPath();
for (String oooType : oooTypes) {
oooType = oooType.replace("\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$
oooType = oooType.replace(" ", "%20"); //$NON-NLS-1$ //$NON-NLS-2$
oooType = "file:///" + oooType; //$NON-NLS-1$
typesReg += " -l " + oooType; //$NON-NLS-1$
}
String prjTypes = prj.getTypesPath().toString();
typesReg += " -l " + prjTypes; //$NON-NLS-1$
return typesReg;
}
}

View File

@ -47,6 +47,20 @@ import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
@ -70,6 +84,11 @@ import org.libreoffice.ide.eclipse.core.model.config.ISdk;
import org.libreoffice.ide.eclipse.core.model.language.AbstractLanguage;
import org.libreoffice.ide.eclipse.core.model.language.IProjectHandler;
import org.libreoffice.ide.eclipse.core.model.language.LanguagesHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* This class implements the UNO-IDL and project nature interface.
@ -131,6 +150,11 @@ public class UnoidlProject implements IUnoidlProject, IProjectNature {
*/
private static final String CONFIG_FILE = ".unoproject"; //$NON-NLS-1$
/**
* The name of the META-INF/manifest.xml file.
*/
private static final String MANIFEST_FILE = "META-INF/manifest.xml"; //$NON-NLS-1$
private IProject mProject;
private String mCompanyPrefix;
@ -424,6 +448,18 @@ public class UnoidlProject implements IUnoidlProject, IProjectNature {
return getFolder(buildDir).getProjectRelativePath();
}
/**
* {@inheritDoc}
*/
@Override
public String getIdlDir() {
String idlDir = getProperty(IDL_DIR);
if (idlDir.startsWith("/")) { //$NON-NLS-1$
idlDir = idlDir.substring(1);
}
return idlDir;
}
/**
* {@inheritDoc}
*/
@ -459,7 +495,7 @@ public class UnoidlProject implements IUnoidlProject, IProjectNature {
*/
@Override
public IPath getTypesPath() {
return new Path("types.rdb"); //$NON-NLS-1$
return new Path(IDLTYPES_FILE);
}
/**
@ -602,9 +638,8 @@ public class UnoidlProject implements IUnoidlProject, IProjectNature {
properties.load(in);
property = properties.getProperty(pPropertyName);
} catch (Exception e) {
String pattern = Messages.getString("UnoidlProject.UnreadableConfigFileWarning"); //$NON-NLS-1$
String msg = MessageFormat.format(pattern, CONFIG_FILE);
PluginLogger.warning(msg, e);
String msg = Messages.getString("UnoidlProject.UnreadableConfigFileWarning"); //$NON-NLS-1$
PluginLogger.warning(MessageFormat.format(msg, CONFIG_FILE), e);
} finally {
try {
in.close();
@ -648,9 +683,8 @@ public class UnoidlProject implements IUnoidlProject, IProjectNature {
getFile(CONFIG_FILE).refreshLocal(IResource.DEPTH_ZERO, null);
} catch (Exception e) {
String pattern = Messages.getString("UnoidlProject.PropertyChangeError"); //$NON-NLS-1$
String message = MessageFormat.format(pattern, name, value);
PluginLogger.warning(message, e);
String msg = Messages.getString("UnoidlProject.PropertyChangeError"); //$NON-NLS-1$
PluginLogger.warning(MessageFormat.format(msg, name, value), e);
} finally {
try {
in.close();
@ -690,15 +724,16 @@ public class UnoidlProject implements IUnoidlProject, IProjectNature {
* {@inheritDoc}
*/
@Override
public void saveJavaBuildProperties(List <IResource> files) {
public void saveJavaBuildProperties(List<IResource> files) {
File buildFile = getBuildFile();
Properties properties = getBuildProperties(buildFile);
String libs = String.join(", ", files.stream().map(IResource::getFullPath)
.map(IPath::makeRelative)
.map(IPath::toString)
.collect(Collectors.toList())); //$NON-NLS-1$
PluginLogger.debug("UnoidlProject.saveJavaBuildProperties libs: " + libs);
properties.put("uno.java.classpath", libs); //$NON-NLS-1$ //$NON-NLS-2$
String msg = Messages.getString("UnoidlProject.SaveJavaBuildProperties"); //$NON-NLS-1$
PluginLogger.debug(MessageFormat.format(msg, buildFile.toString(), libs));
properties.put("uno.java.classpath", libs); //$NON-NLS-1$
saveBuildProperties(properties, buildFile);
}
@ -728,6 +763,170 @@ public class UnoidlProject implements IUnoidlProject, IProjectNature {
return getLanguage().getProjectHandler().getBinFolders(this);
}
/**
* {@inheritDoc}
*/
@Override
public IFile getComponentsFile() {
return getFile(COMPONENTS_FILE);
}
/**
* {@inheritDoc}
*/
@Override
public IFile getTypesFile() {
return getFile(IDLTYPES_FILE);
}
/**
* {@inheritDoc}
*/
@Override
public Document getComponentsDocument() {
return getComponentsDocument(true);
}
/**
* {@inheritDoc}
*/
@Override
public Document getComponentsDocument(boolean create) {
Document document = null;
File file = getComponentsFile().getLocation().toFile();
try {
DocumentBuilder builder = getNewDocumentBuilder();
if (file.exists()) {
document = builder.parse(file);
} else if (create) {
document = builder.newDocument();
}
} catch (IOException | SAXException | ParserConfigurationException e) {
PluginLogger.error(Messages.getString("UnoidlProject.GetComponentsFileError"), e); //$NON-NLS-1$
}
return document;
}
/**
* {@inheritDoc}
*/
@Override
public Element getComponentsElement(Document document) {
Element components = null;
File file = getComponentsFile().getLocation().toFile();
if (file.exists()) {
components = document.getDocumentElement();
} else {
components = document.createElement("components"); //$NON-NLS-1$
components.setAttribute("xmlns", "http://openoffice.org/2010/uno-components"); //$NON-NLS-1$ //$NON-NLS-2$
document.appendChild(components);
}
return components;
}
/**
* {@inheritDoc}
*/
@Override
public boolean removeImplementation(Element components, Element component, String implementation) {
boolean removed = false;
if (component != null) {
int i = 0;
NodeList nodes = component.getElementsByTagName("implementation"); //$NON-NLS-1$
int length = nodes.getLength();
while (i < length && !removed) {
removed = removeImplementation(components, component, nodes.item(i), implementation, length);
i++;
}
}
return removed;
}
/**
* {@inheritDoc}
*/
@Override
public Element createImplementation(Document document, Element component, String implementation, String service) {
Element element = document.createElement("implementation"); //$NON-NLS-1$
element.setAttribute("name", implementation); //$NON-NLS-1$
element.appendChild(createServiceElement(document, service));
component.appendChild(element);
return element;
}
/**
* {@inheritDoc}
*/
@Override
public Element getImplementationElement(Element component, String implementation) {
Element element = null;
int i = 0;
NodeList nodes = component.getElementsByTagName("implementation"); //$NON-NLS-1$
while (i < nodes.getLength() && element == null) {
element = getImplementation(nodes.item(i), implementation);
i++;
}
return element;
}
/**
* {@inheritDoc}
*/
@Override
public boolean addServiceElement(Document document, Element element, String service) {
boolean added = false;
NodeList nodes = element.getElementsByTagName("service"); //$NON-NLS-1$
if (nodes.getLength() > 0) {
if (!hasServiceElement(nodes, service)) {
setServiceElement(nodes, service);
added = true;
}
} else {
element.appendChild(createServiceElement(document, service));
added = true;
}
return added;
}
/**
* {@inheritDoc}
*/
@Override
public void removeImplementationElements(Element element, Element implementation) {
NodeList nodes = element.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
removeImplementationElement(element, nodes.item(i), implementation);
}
}
/**
* {@inheritDoc}
*/
@Override
public void writeComponentsFile(Document document) {
// Check presence of package.components in META-INF/manifest.xml file
checkManifestComponents();
writeXmlFile(document, getComponentsFile().getLocation().toFile());
}
/**
* Check the META-INF/manifest.xml file
* for the application/vnd.sun.star.uno-typelibrary;type=RDB file entry.
*/
@Override
public void checkManifestTypes() {
// Check presence of type.rdb in META-INF/manifest.xml file
File file = getFile(MANIFEST_FILE).getLocation().toFile();
if (!file.exists()) {
createManifestFile();
}
Document document = getManifestXmlDocument(file);
if (document != null) {
String mediatype = "application/vnd.sun.star.uno-typelibrary;type=RDB"; //$NON-NLS-1$
checkManifestFileEntry(document, file, mediatype, IDLTYPES_FILE);
}
}
// *************************************************************************
// IProjectNature Implementation
// *************************************************************************
@ -891,15 +1090,15 @@ public class UnoidlProject implements IUnoidlProject, IProjectNature {
/**
* Toggle an error marker on the project indicating that the there is either no LibreOffice nor SDK set.
*
* @param pSet
* @param enabled
* <code>true</code> if the error marker should be set, <code>false</code> otherwise.
*/
private void setErrorMarker(boolean pSet) {
private void setErrorMarker(boolean enabled) {
IProject prjRes = getProject();
try {
if (pSet) {
if (enabled) {
IMarker marker = prjRes.createMarker(IMarker.PROBLEM);
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
marker.setAttribute(IMarker.MESSAGE, Messages.getString("UnoidlProject.NoOOoSdkError")); //$NON-NLS-1$
@ -907,7 +1106,7 @@ public class UnoidlProject implements IUnoidlProject, IProjectNature {
prjRes.deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO);
}
} catch (CoreException e) {
if (pSet) {
if (enabled) {
PluginLogger.error(Messages.getString("UnoidlProject.CreateMarkerError") + //$NON-NLS-1$
getProjectPath().toString(), e);
} else {
@ -972,4 +1171,232 @@ public class UnoidlProject implements IUnoidlProject, IProjectNature {
return properties;
}
private Element getImplementation(Node node, String implementation) {
Element element = null;
if (node.getNodeType() == Node.ELEMENT_NODE && hasImplementation(node, implementation)) {
element = (Element) node;
}
return element;
}
private boolean hasImplementation(Node node, String implementation) {
return hasNamedAttribute((Element) node, "name", implementation); //$NON-NLS-1$
}
private boolean removeImplementation(Element components, Element component,
Node node, String implementation, int length) {
boolean removed = false;
if (node.getNodeType() == Node.ELEMENT_NODE) {
if (hasImplementation(node, implementation)) {
component.removeChild(node);
// If this is the latest implementation then we also need to remove the component.
if (length == 1) {
components.removeChild(component);
}
removed = true;
}
}
return removed;
}
private void removeImplementationElement(Element parent, Node node, Element implementation) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
if (!element.equals(implementation)) {
parent.removeChild(element);
}
}
}
private void setServiceElement(NodeList nodes, String service) {
Node node = nodes.item(0);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
element.setAttribute("name", service); //$NON-NLS-1$
}
}
private boolean hasServiceElement(NodeList nodes, String service) {
boolean hasService = false;
int i = 0;
while (i < nodes.getLength() && !hasService) {
hasService = hasServiceElement(nodes.item(i), service);
i++;
}
return hasService;
}
private boolean hasServiceElement(Node node, String service) {
boolean hasService = false;
if (node.getNodeType() == Node.ELEMENT_NODE) {
hasService = hasNamedAttribute((Element) node, "name", service); //$NON-NLS-1$
}
return hasService;
}
private boolean hasNamedAttribute(Element element, String name, String value) {
return element.hasAttribute(name) && element.getAttribute(name).equals(value);
}
private Element createServiceElement(Document document, String service) {
Element element = document.createElement("service"); //$NON-NLS-1$
element.setAttribute("name", service); //$NON-NLS-1$
return element;
}
/**
* Check the META-INF/manifest.xml file
* for the application/vnd.sun.star.uno-components file entry.
*/
private void checkManifestComponents() {
File file = getFile(MANIFEST_FILE).getLocation().toFile();
if (!file.exists()) {
createManifestFile();
}
Document document = getManifestXmlDocument(file);
if (document != null) {
String mediatype = "application/vnd.sun.star.uno-components"; //$NON-NLS-1$
checkManifestFileEntry(document, file, mediatype, COMPONENTS_FILE);
}
}
private void createManifestFile() {
File file = getFile(MANIFEST_FILE).getLocation().toFile();
if (!file.exists()) {
Document document = createManifestXmlDocument(file);
if (document != null) {
writeXmlFile(document, file);
}
}
}
private Document getManifestXmlDocument(File file) {
Document document = null;
if (file.exists()) {
try {
document = getNewDocumentBuilder(true).parse(file);
} catch (IOException | SAXException | ParserConfigurationException e) {
PluginLogger.error(Messages.getString("UnoidlProject.GetManifestXmlDocumentError"), e); //$NON-NLS-1$
}
} else {
document = createManifestXmlDocument(file);
}
return document;
}
private Document createManifestXmlDocument(File file) {
Document document = null;
file.getParentFile().mkdir();
String prefix = "manifest"; //$NON-NLS-1$
String uri = "http://openoffice.org/2001/manifest"; //$NON-NLS-1$
try {
document = getNewDocumentBuilder(true).newDocument();
document.appendChild(document.createElementNS(uri, prefix + ":manifest")); //$NON-NLS-1$
} catch (ParserConfigurationException e) {
PluginLogger.error(Messages.getString("UnoidlProject.CreateManifestXmlDocumentError"), e); //$NON-NLS-1$
}
return document;
}
private DocumentBuilder getNewDocumentBuilder() throws ParserConfigurationException {
return getNewDocumentBuilder(false, false);
}
private DocumentBuilder getNewDocumentBuilder(boolean namespace) throws ParserConfigurationException {
return getNewDocumentBuilder(namespace, false);
}
private DocumentBuilder getNewDocumentBuilder(boolean namespace, boolean dtd) throws ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(namespace);
if (dtd) {
factory.setValidating(false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); //$NON-NLS-1$
}
return factory.newDocumentBuilder();
}
private void checkManifestFileEntry(Document document, File file, String mediaType, String fullpath) {
boolean changed = true;
Element entry = null;
Element root = document.getDocumentElement();
String uri = root.getNamespaceURI();
String prefix = root.getPrefix();
NodeList nodes = root.getElementsByTagNameNS(uri, "file-entry"); //$NON-NLS-1$
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
if (element.hasAttributeNS(uri, "media-type") && //$NON-NLS-1$
element.getAttributeNS(uri, "media-type").equals(mediaType)) { //$NON-NLS-1$
entry = element;
break;
}
}
}
if (entry == null) {
entry = document.createElementNS(uri, prefix + ":file-entry"); //$NON-NLS-1$
entry.setAttributeNS(uri, prefix + ":media-type", mediaType); //$NON-NLS-1$
entry.setAttributeNS(uri, prefix + ":full-path", fullpath); //$NON-NLS-1$
root.appendChild(entry);
} else if (!entry.hasAttributeNS(uri, "full-path") || //$NON-NLS-1$
!entry.getAttributeNS(uri, "full-path").equals(fullpath)) { //$NON-NLS-1$
entry.setAttributeNS(uri, prefix + ":full-path", fullpath); //$NON-NLS-1$
} else {
changed = false;
}
if (changed) {
writeXmlFile(document, file);
}
}
private void writeXmlFile(Document document, File file) {
writeXmlFile(document, file, false);
}
private void writeXmlFile(Document document, File file, boolean dtd) {
// Write dom document to a file
try {
// Hide the standalone="no"
document.setXmlStandalone(true);
// Remove whitespaces outside tags
document.normalize();
XPath path = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList) path.evaluate("//text()[normalize-space()='']", //$NON-NLS-1$
document,
XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); ++i) {
Node node = nodes.item(i);
node.getParentNode().removeChild(node);
}
TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute("indent-number", 2); //$NON-NLS-1$
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
if (dtd) {
String doctype = "-//OpenOffice.org//DTD Manifest 1.0//EN"; //$NON-NLS-1$
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, doctype);
transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "Manifest.dtd"); //$NON-NLS-1$
} else {
// XML declaration on its own line
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes"); //$NON-NLS-1$
}
// Pretty print XML
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
try (FileOutputStream stream = new FileOutputStream(file)) {
transformer.transform(new DOMSource(document), new StreamResult(stream));
}
String msg = Messages.getString("UnoidlProject.WriteXmlFile"); //$NON-NLS-1$
PluginLogger.debug(MessageFormat.format(msg, file.toString()));
} catch (IOException | TransformerException | XPathExpressionException e) {
String msg = Messages.getString("UnoidlProject.WriteXmlFileError"); //$NON-NLS-1$
PluginLogger.error(MessageFormat.format(msg, file.toString()), e);
}
}
}

View File

@ -11,7 +11,12 @@ UnoidlProject.BuildFileComment=UNO project Ant build configuration file
UnoidlProject.PropertyChangeError=Error during project property change ({0}, {1})
UnoidlProject.ConfigFileError=Error saving the .unoproject file
UnoidlProject.BuildFileError=Error saving the build.properties file
UnoidlProject.SaveJavaBuildProperties=Writing properties file: {0} with value: {1}
UnoidlProject.InconsistentConfigurationError=The configuration cannot be saved because it's inconsistent
UnoidlProject.GetManifestXmlDocumentError=Error during manifest.xml file reading
UnoidlProject.CreateManifestXmlDocumentError=Error during manifest.xml file creating
UnoidlProject.WriteXmlFileError=Error during writing XML file: {0}
UnoidlProject.WriteXmlFile=Writing XML file: {0}
SDK.NoSettingsDirError=settings directory is missing
SDK.MinSdkVersionError=SDK version has to be at least 2.0.4
SDK.NoDirectoryError=Not an existing directory

View File

@ -34,6 +34,7 @@ import java.io.File;
import java.text.MessageFormat;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
@ -104,9 +105,9 @@ public class OfficeLaunchDelegate extends LaunchConfigurationDelegate {
IProject prj = ResourcesPlugin.getWorkspace().getRoot().getProject(prjName);
TypesBuilder.build(prj, monitor);
PackagePropertiesModel pPropertiesModel = new PackagePropertiesModel(
prj.getFile("package.properties"));
List<IResource> resources = pPropertiesModel.getContents();
IFile properties = prj.getFile("package.properties");
PackagePropertiesModel propertiesModel = new PackagePropertiesModel(properties);
List<IResource> resources = propertiesModel.getContents();
File destFile = exportComponent(unoprj, resources);
monitor.worked(1);
@ -161,21 +162,21 @@ public class OfficeLaunchDelegate extends LaunchConfigurationDelegate {
/**
* Will build and export the .oxt file.
*
* @param pPrj
* @param prj
* the target project.
* @param pResources
* @param resources
* the resources to add to the package
*
* @return the file containing the .oxt file.
* @throws Exception
* if something goes wrong.
*/
private File exportComponent(IUnoidlProject pPrj, List<IResource> pResources) throws Exception {
private File exportComponent(IUnoidlProject prj, List<IResource> resources) throws Exception {
IFolder distFolder = pPrj.getDistFolder();
File destFile = distFolder.getFile(pPrj.getName() + ".oxt").getLocation().toFile();
IFolder distFolder = prj.getDistFolder();
File destFile = distFolder.getFile(prj.getName() + ".oxt").getLocation().toFile();
UnoPackage pack = PackageContentSelector.createPackage(pPrj, destFile, pResources);
UnoPackage pack = PackageContentSelector.createPackage(prj, destFile, resources);
pack.close();
return destFile;

View File

@ -38,6 +38,8 @@ package org.libreoffice.ide.eclipse.core.model;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
@ -47,6 +49,8 @@ import org.eclipse.core.runtime.IPath;
import org.libreoffice.ide.eclipse.core.model.config.IOOo;
import org.libreoffice.ide.eclipse.core.model.config.ISdk;
import org.libreoffice.ide.eclipse.core.model.language.AbstractLanguage;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Interface for a UNO project.
@ -65,6 +69,12 @@ public interface IUnoidlProject {
public static final String XCU_EXTENSION = "xcu"; //$NON-NLS-1$
public static final String IDL_EXTENSION = "idl"; //$NON-NLS-1$
public static final String IDLTYPES_FILE = "types.rdb"; //$NON-NLS-1$
public static final String COMPONENTS_FILE = "package.components"; //$NON-NLS-1$
/**
* Cleans up the project before destroying it.
*/
@ -112,10 +122,10 @@ public interface IUnoidlProject {
/**
* Sets the selected SDK.
*
* @param pSdk
* @param sdk
* the selected SDK
*/
public void setSdk(ISdk pSdk);
public void setSdk(ISdk sdk);
/**
* Set a property to the project.
@ -173,10 +183,10 @@ public interface IUnoidlProject {
/**
* Sets the company prefix.
*
* @param pPrefix
* @param prefix
* new company prefix
*/
public void setCompanyPrefix(String pPrefix);
public void setCompanyPrefix(String prefix);
/**
* Returns the company prefix used in the idl modules and implementation trees. For example, it could be
@ -214,6 +224,11 @@ public interface IUnoidlProject {
*/
public IPath getBuildPath();
/**
* @return the path to the project directory containing the idl files. This path is relative to the project folder.
*/
public String getIdlDir();
/**
* @return the path to the project directory containing the idl files. This path is relative to the project folder.
*/
@ -288,53 +303,159 @@ public interface IUnoidlProject {
* Returns the file handle for the given project relative path. If the file doesn't exists, the handle will be
* <code>null</code>.
*
* @param pPath
* @param path
* the path to the folder to get
*
* @return the folder handle or <code>null</code>
*
* @see org.eclipse.core.resources.IProject#getFile(java.lang.String)
*/
public IFile getFile(IPath pPath);
public IFile getFile(IPath path);
/**
* Returns the file handle for the given project relative path. If the file doesn't exists, the handle will be
* <code>null</code>.
*
* @param pPath
* @param path
* the path to the folder to get
*
* @return the folder handle or <code>null</code>
*
* @see org.eclipse.core.resources.IProject#getFile(java.lang.String)
*/
public IFile getFile(String pPath);
public IFile getFile(String path);
/**
* Returns the file handle for project component XML file.
*
* @return the file handle or <code>null</code>
*/
public IFile getComponentsFile();
/**
* Returns the file handle for idl types file.
*
* @return the file handle or <code>null</code>
*/
public IFile getTypesFile();
/**
* Returns the XML document for project component XML file.
*
* @return the XML document or <code>null</code>
*/
public Document getComponentsDocument();
/**
* Returns the XML document for project component XML file.
*
* @param create create the XML document if not exist
*
* @return the XML document or <code>null</code>
*/
public Document getComponentsDocument(boolean create);
/**
* Returns the components XML element.
*
* @param document the XML document
*
* @return the components XML element.
*/
public Element getComponentsElement(Document document);
/**
* Remove the implementation XML element.
*
* @param components the XML document
* @param component the XML document
* @param implementation the XML document
*
* @return <code>true</code> if implementation has been removed or <code>false</code>
*/
public boolean removeImplementation(Element components, Element component, String implementation);
/**
* Check manifest types file entry.
* @throws ParserConfigurationException
*/
public void checkManifestTypes();
/**
* Get the implementation XML element.
*
* @param element the component XML element
* @param implementation the implementation name
*
* @return the implementation XML element
*/
public Element getImplementationElement(Element element, String implementation);
/**
* Create a new implementation.
*
* @param document the XML document
* @param component the XML component
* @param implName the implementation name
* @param serviceName the service name
*
* @return the created implementation element
*/
public Element createImplementation(Document document, Element component, String implName, String serviceName);
/**
* Check if service exist.
*
* @param document the XML document
* @param element the implementation XML element
* @param service the service name
*
* @return <code>true</code> if service exist or <code>false</code>
*/
public boolean addServiceElement(Document document, Element element, String service);
/**
* Remove all implementation elements from component except the given implementation.
*
* @param element the component XML element
* @param implementation the implementation element to keep
*
*/
public void removeImplementationElements(Element element, Element implementation);
/**
* Write the components XML file.
*
* @param document the XML document
*
*/
public void writeComponentsFile(Document document);
/**
* Returns the folder handle for the given project relative path. If the folder doesn't exists, the handle will be
* <code>null</code>.
*
* @param pPath
* @param path
* the path to the folder to get
*
* @return the folder handle or <code>null</code>
*
* @see org.eclipse.core.resources.IProject#getFolder(java.lang.String)
*/
public IFolder getFolder(IPath pPath);
public IFolder getFolder(IPath path);
/**
* Returns the folder handle for the given project relative path. If the folder doesn't exists, the handle will be
* <code>null</code>.
*
* @param pPath
* @param path
* the path to the folder to get
*
* @return the folder handle or <code>null</code>
*
* @see org.eclipse.core.resources.IProject#getFolder(java.lang.String)
*/
public IFolder getFolder(String pPath);
public IFolder getFolder(String path);
/**
* Defines the directory containing the IDL files.
@ -347,10 +468,10 @@ public interface IUnoidlProject {
/**
* Defines the directory containing the sources.
*
* @param pSourcesDir
* @param sourcesDir
* the sources directory
*/
public void setSourcesDir(String pSourcesDir);
public void setSourcesDir(String sourcesDir);
/**
* Saves the UNO project configuration in a hidden file.

View File

@ -264,16 +264,16 @@ public class UnoPackage {
/**
* Adds the directory.
*
* @param pPathInArchive
* @param pathInArchive
* the path in archive
* @param directory
* the directory
*/
public void addDirectory(final String pPathInArchive, final File directory) {
public void addDirectory(final String pathInArchive, final File directory) {
if (!directory.isDirectory()) {
throw new IllegalArgumentException(directory + " is not a directory!");
}
this.addDirectory(pPathInArchive, directory, new String[0], new String[0]);
this.addDirectory(pathInArchive, directory, new String[0], new String[0]);
}
/**
@ -388,21 +388,22 @@ public class UnoPackage {
* Add a UNO components XML file to the package.
*
* @param pathInArchive
* @param pFile
* @param file
* the file to add to the package
* @param pPlatform
* @param platform
* optional parameter to use only with native type. Please refer
* to the OOo Developer's Guide for more information.
*/
public void addComponentsFile(String pathInArchive, File pFile, String pPlatform) {
if (!pFile.isFile())
throw new IllegalArgumentException("pFile [" + pFile + "] is not a file");
public void addComponentsFile(String pathInArchive, File file, String platform) {
if (!file.isFile()) {
throw new IllegalArgumentException("pFile [" + file + "] is not a file");
}
// Do not change the extension from now
initializeOutput();
mManifest.addComponentsFile(pathInArchive, pPlatform);
addZipContent(pathInArchive, pFile);
mManifest.addComponentsFile(pathInArchive, platform);
addZipContent(pathInArchive, file);
}
/**
@ -644,22 +645,22 @@ public class UnoPackage {
* This could be used for example for images.
* </p>
*
* @param pPathInArchive
* @param pathInArchive
* the path in archive
* @param file
* the file or directory to add.
*/
public void addOtherFile(String pPathInArchive, File file) {
public void addOtherFile(String pathInArchive, File file) {
if (!file.isFile()) {
throw new IllegalArgumentException("File [" + file.getAbsolutePath() + "] is not a file");
}
pPathInArchive = FilenameUtils.separatorsToUnix(pPathInArchive);
pathInArchive = FilenameUtils.separatorsToUnix(pathInArchive);
// Do not change the extension from now
initializeOutput();
addZipContent(pPathInArchive, file);
addZipContent(pathInArchive, file);
}
/**
@ -718,7 +719,7 @@ public class UnoPackage {
return result;
}
private void addManifestFile(ZipOutputStream pZipOut) throws IOException {
private void addManifestFile(ZipOutputStream zipOut) throws IOException {
File manifestFile = mReadManifestFile;
if (manifestFile == null) {
manifestFile = createManifestFile();
@ -730,7 +731,7 @@ public class UnoPackage {
}
}
ZipContent manifest = new ZipContent("META-INF/manifest.xml", manifestFile);
manifest.writeContentToZip(pZipOut);
manifest.writeContentToZip(zipOut);
}
private File createManifestFile() throws IOException {
@ -769,11 +770,11 @@ public class UnoPackage {
* Add the path to a resource to clean after having exported the package. The resource won't be cleaned if the
* package isn't exported.
*
* @param pPath
* @param path
* the path to the resource to clean.
*/
public void addToClean(File pPath) {
mToClean.add(pPath);
public void addToClean(File path) {
mToClean.add(path);
}
/**
@ -792,13 +793,13 @@ public class UnoPackage {
/**
* Recursively add the file or directory to the Zip entries.
*
* @param pRelativePath
* @param relativePath
* the relative path of the file to add
* @param file
* the file or directory to add
*/
private void addZipContent(String pRelativePath, File file) {
addZipContent(pRelativePath, file, new String[0], new String[0]);
private void addZipContent(String relativePath, File file) {
addZipContent(relativePath, file, new String[0], new String[0]);
}
/**
@ -850,15 +851,15 @@ public class UnoPackage {
/**
* Checks if the resource is a dialog library.
*
* @param pRes
* @param res
* the resource to check
*
* @return <code>true</code> if the resource is a dialog library, <code>false</code> in any other case
*/
private boolean isDialogLibrary(File pRes) {
private boolean isDialogLibrary(File res) {
boolean result = false;
if (pRes.isDirectory()) {
result = new File(pRes, DIALOG_LIBRARY_INDEX).exists();
if (res.isDirectory()) {
result = new File(res, DIALOG_LIBRARY_INDEX).exists();
}
return result;
}
@ -866,15 +867,15 @@ public class UnoPackage {
/**
* Checks if the resource is a basic library.
*
* @param pRes
* @param res
* the resource to check
*
* @return <code>true</code> if the resource is a basic library, <code>false</code> in any other case
*/
private boolean isBasicLibrary(File pRes) {
private boolean isBasicLibrary(File res) {
boolean result = false;
if (pRes.isDirectory()) {
result = new File(pRes, BASIC_LIBRARY_INDEX).exists();
if (res.isDirectory()) {
result = new File(res, BASIC_LIBRARY_INDEX).exists();
}
return result;
}

View File

@ -5,10 +5,6 @@
<classpathentry kind="src" path="source"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ANT"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/LO-Classes"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -36,20 +36,20 @@
************************************************************************/
package org.libreoffice.ide.eclipse.java;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.libreoffice.ide.eclipse.core.PluginLogger;
import org.libreoffice.ide.eclipse.core.model.IUnoidlProject;
import org.libreoffice.ide.eclipse.core.model.ProjectsManager;
@ -72,18 +72,18 @@ public class JavaResourceDeltaVisitor implements IResourceDeltaVisitor {
IResource res = delta.getResource();
if (res != null && res.getType() == IResource.FILE) {
IProject project = delta.getResource().getProject();
IUnoidlProject prj = ProjectsManager.getProject(project.getName());
if (prj != null) {
IProject prj = res.getProject();
IUnoidlProject unoPrj = ProjectsManager.getProject(prj.getName());
if (unoPrj != null) {
// The resource is a UNO project or is contained in a UNO project
visitChildren = true;
// Check if the resource is a service implementation
if (delta.getKind() == IResourceDelta.ADDED) {
addImplementation(prj, res);
addImplementation(unoPrj, res);
} else if (delta.getKind() == IResourceDelta.REMOVED) {
removeImplementation(prj, delta, res);
removeImplementation(unoPrj, res);
} else if (delta.getKind() == IResourceDelta.CHANGED) {
changeJavaBuildPorperties(prj, res);
changeImplementation(unoPrj, res);
}
}
}
@ -95,23 +95,14 @@ public class JavaResourceDeltaVisitor implements IResourceDeltaVisitor {
* Remove the delta resource from the implementations.
*
* @param prj the concerned UNO project
* @param delta the delta to remove
* @param res the concerned delta resource
*/
private void removeImplementation(IUnoidlProject prj, IResourceDelta delta, IResource res) {
if (res.getName().endsWith(".java")) { //$NON-NLS-1$
String path = delta.getProjectRelativePath().toString();
path = path.replace(".java", ""); //$NON-NLS-1$ //$NON-NLS-2$
path = path.replace("/", "."); //$NON-NLS-1$ //$NON-NLS-2$
Vector<String> classes = RegistrationHelper.readClassesList(prj);
for (String implName : classes) {
if (path.endsWith(implName)) {
RegistrationHelper.removeImplementation(prj, implName);
}
private void removeImplementation(IUnoidlProject prj, IResource res) {
if (isJavaSourceFile(res)) {
IType type = getJavaImplementationType(prj.getProject(), res);
if (type != null) {
RegistrationHelper.removeImplementation(prj, type.getFullyQualifiedName());
}
} else if (res.getName().endsWith(".jar")) {
RegistrationHelper.checkClassesListFile(prj);
}
}
@ -122,10 +113,13 @@ public class JavaResourceDeltaVisitor implements IResourceDeltaVisitor {
* @param res the concerned delta resource
*/
private void addImplementation( IUnoidlProject prj, IResource res) {
if (res.getName().endsWith(".java")) { //$NON-NLS-1$
String className = getJavaServiceImpl(res);
if (className != null) {
RegistrationHelper.addImplementation(prj, className);
if (isJavaSourceFile(res)) {
IType type = getJavaImplementationType(prj.getProject(), res);
if (type != null) {
IField field = getServiceNameField(type);
if (field.exists()) {
addImplementation(prj, type, field);
}
}
}
}
@ -136,82 +130,130 @@ public class JavaResourceDeltaVisitor implements IResourceDeltaVisitor {
* @param prj the concerned UNO project
* @param res the concerned delta resource
*/
private void changeJavaBuildPorperties(IUnoidlProject prj, IResource res) {
if (res.getName().equals(".classpath") && //$NON-NLS-1$
prj.hasBuildFile()) {
List <IResource> libs = JavaClassPathProvider.getWorkspaceLibs(prj);
PluginLogger.debug("Found " + libs.size() + " Jars");
prj.saveJavaBuildProperties(libs);
private void changeImplementation(IUnoidlProject prj, IResource res) {
if (isEclipseClassPath(res) && prj.hasBuildFile()) {
changeJavaBuildProperties(prj, res);
} else if (isJavaSourceFile(res)) {
IType type = getJavaImplementationType(prj.getProject(), res);
if (type != null) {
IField field = getServiceNameField(type);
if (field.exists()) {
addImplementation(prj, type, field);
} else {
RegistrationHelper.removeImplementation(prj, type.getFullyQualifiedName());
}
}
}
}
/**
* Get the java service implementation class name.
* Add the type to the implementations.
*
* @param prj the concerned UNO project
* @param type the concerned delta resource
* @param field the concerned delta resource
*/
private void addImplementation(IUnoidlProject prj, IType type, IField field) {
String serviceName = getServiceNameValue(field);
if (serviceName != null) {
RegistrationHelper.addImplementation(prj, type.getFullyQualifiedName(), serviceName);
}
}
/**
* Is resource a Java source file.
*
* @param res the resource to check.
* @return <code>class name</code> if it contains the necessary static methods for Java
* @return <code>true</code> if resource is a Java source file or <code>false</code> if not.
*/
private boolean isJavaSourceFile(IResource res) {
return "java".equals(res.getFileExtension()); //$NON-NLS-1$
}
/**
* Is resource the Eclipse .classpath.
*
* @param res the resource to check.
* @return <code>true</code> if resource is the Eclipse .classpath file or <code>false</code> if not.
*/
private boolean isEclipseClassPath(IResource res) {
return res.getName().equals(".classpath"); //$NON-NLS-1$
}
/**
* Change the delta resource to the java project.
*
* @param prj the concerned UNO project
* @param res the concerned delta resource
*/
private void changeJavaBuildProperties(IUnoidlProject prj, IResource res) {
List <IResource> libs = JavaClassPathProvider.getWorkspaceLibs(prj);
PluginLogger.debug("Found " + libs.size() + " Jars"); //$NON-NLS-1$ //$NON-NLS-2$
prj.saveJavaBuildProperties(libs);
}
/**
* Get the java type of resource.
*
* @param prj the project.
* @param res the resource to check.
* @return <code>type</code> if it contains the necessary static methods for Java
* UNO service implementation registration or <code>null</code> if not.
*/
private String getJavaServiceImpl(IResource res) {
private IType getJavaImplementationType(IProject prj, IResource res) {
String className = null;
/*
* For sure the resource is a Java class file.
* Now the file has to be read to find out if it contains the two
* following methods:
*
* + public static XSingleComponentFactory __getComponentFactory
* + public static boolean __writeRegistryServiceInfo(XRegistryKey xRegistryKey )
*/
FileInputStream in = null;
BufferedReader reader = null;
try {
File file = res.getLocation().toFile();
in = new FileInputStream(file);
reader = new BufferedReader(new InputStreamReader(in));
// Read the file into a string without line delimiters
String line = reader.readLine();
String fileContent = ""; //$NON-NLS-1$
while (line != null) {
fileContent = fileContent + line;
line = reader.readLine();
}
String getFactoryRegex = "public\\s+static\\s+XSingleComponentFactory" + //$NON-NLS-1$
"\\s+__getComponentFactory"; //$NON-NLS-1$
boolean containsGetFactory = fileContent.split(getFactoryRegex).length > 1;
String writeServiceRegex = "public\\s+static\\s+boolean\\s+__writeRegistryServiceInfo"; //$NON-NLS-1$
boolean containsWriteService = fileContent.split(writeServiceRegex).length > 1;
// Do not consider the RegistrationHandler class as a service implementation
if (containsGetFactory && containsWriteService &&
!res.getName().equals("RegistrationHandler.java")) { //$NON-NLS-1$
/*
* Computes the class name
*/
Matcher m3 = Pattern.compile("[^;]*package\\s+([^;]+);.*").matcher(fileContent); //$NON-NLS-1$
if (m3.matches()) {
String packageName = m3.group(1);
String fileName = res.getName();
className = fileName.substring(0, fileName.length() - ".java".length()); //$NON-NLS-1$
className = packageName + "." + className; //$NON-NLS-1$
}
}
} catch (Exception e) {
// nothing to log
} finally {
IType implementation = null;
IJavaElement element = JavaCore.create(res);
if (element.getElementType() == IJavaElement.COMPILATION_UNIT) {
ICompilationUnit unit = (ICompilationUnit) element;
String[] parameters = {"QXComponentContext;"}; //$NON-NLS-1$
try {
reader.close();
in.close();
} catch (Exception e) {
for (IType type : unit.getAllTypes()) {
// Does this resource has a constructor with XComponentContext has unique parameter
IMethod method = type.getMethod(type.getElementName(), parameters);
if (method.exists() && method.isConstructor()) {
implementation = type;
break;
}
}
} catch (JavaModelException e) {
e.printStackTrace();
}
}
return className;
return implementation;
}
/**
* Get service name filed.
*
* @param type the type to get field.
* @return the service name field from the given type.
*/
private IField getServiceNameField(IType type) {
return type.getField("m_serviceName"); //$NON-NLS-1$
}
/**
* Get service name value.
*
* @param field the field having service name.
* @return the service name value from the given field.
*/
private String getServiceNameValue(IField field) {
Object obj = null;
try {
obj = field.getConstant();
} catch (JavaModelException e) { }
String value = null;
if (obj != null) {
value = (String) obj;
if (value != null && !value.isEmpty() &&
value.charAt(0) == '"' &&
value.charAt(value.length() - 1) == '"') {
value = value.substring(1, value.length() - 1);
}
}
return value;
}
}

View File

@ -37,15 +37,10 @@
************************************************************************/
package {0};
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.lang.reflect.Field;
import com.sun.star.lang.XSingleComponentFactory;
import com.sun.star.registry.XRegistryKey;
import com.sun.star.lib.uno.helper.Factory;
/**
* Component main registration class.
@ -58,118 +53,53 @@ import com.sun.star.registry.XRegistryKey;
public class RegistrationHandler '{'
/**
* Get a component factory for the implementations handled by this class.
*
* <p>This method calls all the methods of the same name from the classes listed
* in the <code>RegistrationHandler.classes</code> file. <strong>This method
* should not be modified.</strong></p>
*
* @param sImplementationName the name of the implementation to create.
*
* @return the factory which can create the implementation.
*/
public static XSingleComponentFactory __getComponentFactory(String sImplementationName) '{'
XSingleComponentFactory xFactory = null;
Class<?>[] classes = findServicesImplementationClasses();
int i = 0;
while (i < classes.length && xFactory == null) '{'
Class<?> clazz = classes[i];
if (sImplementationName.equals(clazz.getCanonicalName())) '{'
try '{'
Class<?>[] getTypes = new Class[]'{'String.class};
Method getFactoryMethod = clazz.getMethod("__getComponentFactory", getTypes);
Object o = getFactoryMethod.invoke(null, sImplementationName);
xFactory = (XSingleComponentFactory)o;
} catch (Exception e) '{'
// Nothing to do: skip
System.err.println("Error happened");
e.printStackTrace();
}
}
i++;
* Get a component factory for the implementations handled by this class.
*
* <p>This method retrieve the Class object associated with the class with the given
* <code>implementation</code> String parameter. If this class has a <code>m_serviceNames</code>
* static field then the list of its services will be used, otherwise the <code>implementation</code>
* parameter will be the only entry in the list of supported services.
* <strong>This method should not be modified.</strong></p>
*
* @param implementation the name of the implementation to create.
*
* @return the factory which can create the implementation.
*/
public static XSingleComponentFactory __getComponentFactory(final String implementation) '{'
Class<?> clazz = null;
try '{'
clazz = Class.forName(implementation);
} catch (ClassNotFoundException e) '{'
// Nothing to do: skip
System.err.println("Error happened");
e.printStackTrace();
}
return xFactory;
}
/**
* Writes the services implementation informations to the UNO registry.
*
* <p>This method calls all the methods of the same name from the classes listed
* in the <code>RegistrationHandler.classes</code> file. <strong>This method
* should not be modified.</strong></p>
*
* @param xRegistryKey the root registry key where to write the informations.
*
* @return <code>true</code> if the informations have been successfully written
* to the registry key, <code>false</code> otherwise.
*/
public static boolean __writeRegistryServiceInfo(XRegistryKey xRegistryKey) '{'
Class<?>[] classes = findServicesImplementationClasses();
boolean success = true;
int i = 0;
while (i < classes.length && success) '{'
Class<?> clazz = classes[i];
XSingleComponentFactory factory = null;
if (clazz != null) '{'
String [] services = null;
try '{'
Class<?>[] writeTypes = new Class[]'{'XRegistryKey.class};
Method getFactoryMethod = clazz.getMethod("__writeRegistryServiceInfo", writeTypes);
Object o = getFactoryMethod.invoke(null, xRegistryKey);
success = success && ((Boolean)o).booleanValue();
} catch (Exception e) '{'
success = false;
int i = 0;
Field[] fields = clazz.getDeclaredFields();
while (i < fields.length && services == null) '{'
Field field = fields[i];
if (field.getName().equals("m_serviceNames")) '{'
field.setAccessible(true);
services = (String[]) field.get(null);
}
i++;
}
} catch (SecurityException | IllegalArgumentException | IllegalAccessException e) '{'
// Nothing to do: skip
System.err.println("Error happened");
e.printStackTrace();
}
i++;
}
return success;
}
/**
* @return all the UNO implementation classes.
*/
private static Class<?>[] findServicesImplementationClasses() '{'
ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
InputStream in = RegistrationHandler.class.getResourceAsStream("RegistrationHandler.classes");
LineNumberReader reader = new LineNumberReader(new InputStreamReader(in));
try '{'
String line = reader.readLine();
while (line != null) '{'
if (!line.equals("")) '{'
line = line.trim();
try '{'
Class<?> clazz = Class.forName(line);
Class<?>[] writeTypes = new Class[]'{'XRegistryKey.class};
Class<?>[] getTypes = new Class[]'{'String.class};
Method writeRegMethod = clazz.getMethod("__writeRegistryServiceInfo", writeTypes);
Method getFactoryMethod = clazz.getMethod("__getComponentFactory", getTypes);
if (writeRegMethod != null && getFactoryMethod != null) '{'
classes.add(clazz);
}
} catch (Exception e) '{'
e.printStackTrace();
}
}
line = reader.readLine();
if (services == null) '{'
services = new String[] '{'implementation};
System.err.println("No <m_serviceNames> static field, defaulting to: " + implementation);
}
} catch (IOException e) '{'
e.printStackTrace();
} finally '{'
try '{'
reader.close();
in.close();
} catch (Exception e) '{' }
factory = Factory.createComponentFactory(clazz, services);
}
return classes.toArray(new Class[classes.size()]);
return factory;
}
}

View File

@ -36,28 +36,13 @@
************************************************************************/
package org.libreoffice.ide.eclipse.java.registration;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.IPath;
import org.eclipse.swt.widgets.Display;
import org.libreoffice.ide.eclipse.core.PluginLogger;
import org.libreoffice.ide.eclipse.core.model.IUnoidlProject;
import org.libreoffice.ide.eclipse.java.utils.TemplatesHelper;
import org.libreoffice.plugin.core.utils.ErrorDlg;
import org.libreoffice.plugin.core.utils.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeException;
/**
* This class provides utility methods to generate the class and files needed
@ -71,55 +56,60 @@ public abstract class RegistrationHelper {
* Creates all the necessary files for the java registration of UNO services
* implementations to the <code>regcomp</code> tool.
*
* @param pProject the project where to create the registration handler
* @param project the project where to create the registration handler
*/
public static void generateFiles(IUnoidlProject pProject) {
public static void generateFiles(IUnoidlProject project) {
// Copy the RegistrationHandler.java.tpl file
TemplatesHelper.copyTemplate(pProject, CLASS_FILENAME + TemplatesHelper.JAVA_EXT,
RegistrationHelper.class, new String());
TemplatesHelper.copyTemplate(project, CLASS_FILENAME + TemplatesHelper.JAVA_EXT,
RegistrationHelper.class, new String());
// Create the empty RegistrationHandler.classes file
ByteArrayInputStream empty = new ByteArrayInputStream(new byte[0]);
try {
File listFile = getClassesListFile(pProject).getLocation().toFile();
listFile.createNewFile();
} catch (IOException e) {
PluginLogger.error(Messages.getString("RegistrationHelper.WriteClassesListError"), e); //$NON-NLS-1$
} finally {
try {
empty.close();
} catch (Exception e) {
}
}
}
/**
* Add a UNO service implementation to the list of the project ones.
*
* @param project the project where to add the implementation
* @param implName the fully qualified name of the implementation to add,
* @param implementation the fully qualified name of the implementation to add,
* @param service the fully qualified name of the UNO service to add,
* eg: <code>org.libreoffice.comp.test.MyServiceImpl</code>
*/
public static void addImplementation(IUnoidlProject project, String implName) {
Vector<String> classes = readClassesList(project);
if (!classes.contains(implName)) {
classes.add(implName);
public static void addImplementation(IUnoidlProject project, String implementation, String service) {
Element components = null;
Document document = project.getComponentsDocument();
if (document != null) {
components = project.getComponentsElement(document);
}
if (components != null) {
Element component = getJavaComponent(project, document, components);
if (component != null) {
if (addImplementation(project, document, component, implementation, service)) {
project.writeComponentsFile(document);
}
}
}
writeClassesList(project, classes);
}
/**
* remove a UNO service implementation from the list of the project ones.
*
* @param project the project where to remove the implementation
* @param implName the fully qualified name of the implementation to remove,
* @param implementation the fully qualified name of the implementation to remove,
* eg: <code>org.libreoffice.comp.test.MyServiceImpl</code>
*/
public static void removeImplementation(IUnoidlProject project, String implName) {
Vector<String> classes = readClassesList(project);
classes.remove(implName);
writeClassesList(project, classes);
public static void removeImplementation(IUnoidlProject project, String implementation) {
boolean removed = false;
Document document = project.getComponentsDocument(false);
if (document != null) {
Element components = project.getComponentsElement(document);
if (components != null) {
Element component = getJavaComponent(project, document, components, false);
removed = project.removeImplementation(components, component, implementation);
}
}
if (removed) {
project.writeComponentsFile(document);
}
}
/**
@ -128,141 +118,68 @@ public abstract class RegistrationHelper {
* The registration class name is generally
* <code>&lt;COMPANY.PREFIX&gt;.&lt;OUTPUTEXT&gt;.RegistrationHandler</code>.
*
* @param pProject the project for which to compute the class name
* @param project the project for which to compute the class name
* @return the registration class name
*/
public static String getRegistrationClassName(IUnoidlProject pProject) {
public static String getRegistrationClassName(IUnoidlProject project) {
// Compute the name of the main implementation class
String implPkg = pProject.getCompanyPrefix() + "." + pProject.getOutputExtension(); //$NON-NLS-1$
String implPkg = project.getCompanyPrefix() + "." + project.getOutputExtension(); //$NON-NLS-1$
return implPkg + "." + CLASS_FILENAME; //$NON-NLS-1$
}
/**
* Read the implementation classes list of the given UNO project.
*
* @param pProject the UNO project
*
* @return the implementation classes list
*/
public static Vector<String> readClassesList(IUnoidlProject pProject) {
Vector<String> classes = new Vector<String>();
IFile list = getClassesListFile(pProject);
File file = list.getLocation().toFile();
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
PluginLogger.error(Messages.getString("RegistrationHelper.WriteClassesListError"), e); //$NON-NLS-1$
}
private static boolean addImplementation(IUnoidlProject project, Document document, Element component,
String implementation, String service) {
boolean added = false;
setComponentUri(component, project);
Element element = project.getImplementationElement(component, implementation);
if (element != null) {
added = project.addServiceElement(document, element, service);
} else {
project.createImplementation(document, component, implementation, service);
added = true;
}
return added;
}
// First read all the lines
FileInputStream in = null;
BufferedReader reader = null;
try {
in = new FileInputStream(file);
reader = new BufferedReader(new InputStreamReader(in));
private static Element getJavaComponent(IUnoidlProject project, Document document, Element components) {
return getJavaComponent(project, document, components, true);
}
String line = reader.readLine();
while (line != null) {
if (!classes.contains(line)) {
classes.add(line);
private static Element getJavaComponent(IUnoidlProject project, Document document,
Element components, boolean create) {
Element component = null;
NodeList nodes = components.getElementsByTagName("component"); //$NON-NLS-1$
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
if (isJavaComponent(element)) {
component = element;
break;
}
line = reader.readLine();
}
} catch (Exception e) {
} finally {
try {
reader.close();
in.close();
} catch (Exception e) {
}
}
return classes;
if (component == null && create) {
component = createJavaComponent(project, document, components);
}
return component;
}
/**
* Writes the implementation classes list to the UNO project.
*
* @param project the project for which to write the list
* @param classes the classes to write
*/
private static void writeClassesList(IUnoidlProject project, Vector<String> classes) {
IFile list = getClassesListFile(project);
File file = list.getLocation().toFile();
FileWriter writer = null;
try {
writer = new FileWriter(file);
for (String implClass : classes) {
writer.append(implClass + "\n"); //$NON-NLS-1$
}
} catch (IOException e) {
PluginLogger.error(Messages.getString("RegistrationHelper.WriteClassesListError"), e); //$NON-NLS-1$
} finally {
try {
writer.close();
} catch (Exception e) {
}
}
// update the list file in the workspace
new FileRefreshJob(list).schedule();
private static Element createJavaComponent(IUnoidlProject project, Document document, Element components) {
Element component = document.createElement("component"); //$NON-NLS-1$
component.setAttribute("loader", "com.sun.star.loader.Java2"); //$NON-NLS-1$ //$NON-NLS-2$
setComponentUri(component, project);
components.appendChild(component);
return component;
}
/**
* Get the classes list file for the given UNO project.
*
* @param pProject the UNO project to get the list file from
*
* @return the implementation classes file of the project.
*/
private static IFile getClassesListFile(IUnoidlProject pProject) {
// Get the path where to place the class and the implementations list
IPath relPath = pProject.getImplementationPath();
IFolder dest = pProject.getFolder(relPath);
return dest.getFile("RegistrationHandler.classes"); //$NON-NLS-1$
private static boolean isJavaComponent(Element component) {
return component.hasAttribute("loader") && //$NON-NLS-1$
component.getAttribute("loader").equals("com.sun.star.loader.Java2"); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Check if the RegistrationHandler.classes file exist, readable and not empty
* <code>org.libreoffice.ide.eclipse.java.JavaResourceDeltaVisitor</code>.
*
* @param pProject the project where to check empty file
*/
public static void checkClassesListFile(IUnoidlProject pProject) {
// get RegistrationHandler.classes
IFile iClassesListFile = getClassesListFile(pProject);
File classesListFile = iClassesListFile.getLocation().toFile();
Path listFile = classesListFile.toPath();
String errMsg = null;
if (!Files.exists(listFile)) {
errMsg = Messages.getString("RegistrationHelper.RegistrationHandlerNotExist");
} else if (!Files.isRegularFile(listFile)) {
errMsg = Messages.getString("RegistrationHelper.RegistrationHandlerNotAFile");
} else if (!Files.isReadable(listFile)) {
errMsg = Messages.getString("RegistrationHelper.RegistrationHandlerNotReadable");
} else if (classesListFile.length() == 0) {
errMsg = Messages.getString("RegistrationHelper.RegistrationHandlerEmptyClassError");
}
if (StringUtils.isNotEmpty(errMsg)) {
PluginLogger.error("Error checking RegistrationHandler.classes: " + classesListFile);
PluginLogger.error(errMsg);
String packageStr = pProject.getCompanyPrefix() + "." + pProject.getOutputExtension();
String extErr = errMsg + System.lineSeparator()
+ "The file RegistrationHandler.classes must be in the package: " + System.lineSeparator() + packageStr;
Display.getDefault().syncExec(new ErrorDlg(extErr));
throw new OpenOfficeException(extErr);
}
private static void setComponentUri(Element component, IUnoidlProject project) {
component.setAttribute("uri", project.getName() + ".jar"); //$NON-NLS-1$ //$NON-NLS-2$
}
}

View File

@ -1,7 +1 @@
FileRefreshJob.Error=Can't refresh the registration classes file
RegistrationHelper.WriteClassesListError=Error during classes list writing
RegistrationHelper.RegistrationHandlerEmptyClassError=The RegistrationHandler.classes is empty, exported .oxt extension will not work properly
RegistrationHelper.RegistrationHandlerNotExist=The RegistrationHandler.classes does not exist, exported .oxt extension will not work properly
RegistrationHelper.RegistrationHandlerNotAFile=The RegistrationHandler.classes is not a File, exported .oxt extension will not work properly
RegistrationHelper.RegistrationHandlerNotReadable=The RegistrationHandler.classes is not readable, exported .oxt extension will not work properly

View File

@ -5,10 +5,6 @@
<classpathentry kind="src" path="source"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ANT"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/LO-Classes"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -36,10 +36,17 @@
************************************************************************/
package org.libreoffice.ide.eclipse.python;
import org.eclipse.core.resources.IProject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.libreoffice.ide.eclipse.core.model.IUnoidlProject;
import org.libreoffice.ide.eclipse.core.model.ProjectsManager;
@ -58,20 +65,21 @@ public class PythonResourceDeltaVisitor implements IResourceDeltaVisitor {
boolean visitChildren = true;
if (!(delta.getResource() instanceof IWorkspaceRoot)) {
IResource res = delta.getResource();
if (res != null && res.getType() == IResource.FILE && isPythonSourceFile(res)) {
IProject project = delta.getResource().getProject();
IUnoidlProject unoprj = ProjectsManager.getProject(project.getName());
if (unoprj != null) {
IUnoidlProject project = ProjectsManager.getProject(res.getProject().getName());
if (project != null) {
// The resource is a UNO project or is contained in a UNO project
visitChildren = true;
// Check if the resource is a service implementation
if (delta.getKind() == IResourceDelta.ADDED) {
addImplementation(delta, unoprj);
addImplementation(project, res);
} else if (delta.getKind() == IResourceDelta.REMOVED) {
removeImplementation(delta, unoprj);
removeImplementation(project, res);
} else if (delta.getKind() == IResourceDelta.CHANGED) {
changeImplementation(project, res);
}
}
}
@ -79,25 +87,119 @@ public class PythonResourceDeltaVisitor implements IResourceDeltaVisitor {
return visitChildren;
}
private boolean isPythonSourceFile(IResource res) {
return ((IFile) res).getFileExtension().equals("py");
}
/**
* Remove the delta resource from the implementations.
*
* @param delta the delta to remove
* @param unoProject the concerned UNO project
* @param prj the concerned UNO project
* @param res the resource to remove
*/
private void removeImplementation(IResourceDelta delta,
IUnoidlProject unoProject) {
// Nothing to do for Python
private void removeImplementation(IUnoidlProject prj, IResource res) {
String content = getPythonFileContent(res);
if (content != null) {
String uri = res.getProjectRelativePath().toString();
RegistrationHelper.removeImplementation(prj, uri);
}
}
/**
* Add the delta resource to the implementations.
*
* @param delta the delta resource to add.
* @param unoProject the concerned UNO project
* @param prj the concerned UNO project
* @param res the resource to add.
*/
private void addImplementation(IResourceDelta delta, IUnoidlProject unoProject) {
// Nothing to do for Python
private void addImplementation(IUnoidlProject prj, IResource res) {
String content = getPythonFileContent(res);
if (content != null) {
String uri = res.getProjectRelativePath().toString();
String serviceName = getPythonServiceName(content);
if (serviceName != null) {
RegistrationHelper.addImplementation(prj, uri, serviceName);
}
}
}
/**
* Change the delta resource to the java project.
*
* @param prj the concerned UNO project
* @param res the concerned resource
*/
private void changeImplementation(IUnoidlProject prj, IResource res) {
String content = getPythonFileContent(res);
if (content != null) {
String uri = res.getProjectRelativePath().toString();
String serviceName = getPythonServiceName(content);
if (serviceName != null) {
RegistrationHelper.addImplementation(prj, uri, serviceName);
} else {
RegistrationHelper.removeImplementation(prj, uri);
}
}
}
/**
* Get the python source file content.
*
* @param res the resource to check.
* @return <code>file content</code> if it contains the necessary static methods for Python
* UNO service implementation registration or <code>null</code> if not.
*/
private String getPythonFileContent(IResource res) {
String fileContent = null;
FileInputStream in = null;
BufferedReader reader = null;
try {
File file = res.getLocation().toFile();
in = new FileInputStream(file);
reader = new BufferedReader(new InputStreamReader(in));
// Read the .py file into a string without line delimiters
StringBuffer buffer = new StringBuffer();
String line = reader.readLine();
while (line != null) {
buffer.append(line);
buffer.append(' ');
line = reader.readLine();
}
String content = buffer.toString();
String implHelper = "g_ImplementationHelper *= *unohelper.ImplementationHelper *\\( *\\)"; //$NON-NLS-1$
if (content.split(implHelper).length > 1) {
fileContent = content;
}
} catch (Exception e) {
// nothing to log
} finally {
try {
reader.close();
in.close();
} catch (Exception e) { }
}
return fileContent;
}
/**
* Get the python service implementation name.
*
* @param content the .py file content.
* @return <code>service name</code> if it contains the necessary static methods for Python
* UNO service implementation registration or <code>null</code> if not.
*/
private String getPythonServiceName(String content) {
String serviceName = null;
String pattern = "g_ServiceName *= *[\"']([^\"' ][a-zA-Z0-9\\.\\-_]+)[\"']"; //$NON-NLS-1$
Matcher matcher = Pattern.compile(pattern).matcher(content);
if (matcher.find()) {
serviceName = matcher.group(1);
}
return serviceName;
}
}

View File

@ -0,0 +1,163 @@
/*************************************************************************
* The Contents of this file are made available subject to the terms of
* the GNU Lesser General Public License Version 2.1
*
* Sun Microsystems Inc., October, 2000
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc..
*
* Copyright: 2002 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): Cedric Bosdonnat
*
*
************************************************************************/
package org.libreoffice.ide.eclipse.python;
import org.libreoffice.ide.eclipse.core.model.IUnoidlProject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* This class provides utility methods to generate the .components files needed
* by the UNO services implementation registration.
*/
public abstract class RegistrationHelper {
/**
* Add a UNO service implementation to the list of the project ones.
*
* @param project the project where to add the implementation
* @param uri the project relative file name of the implementation to add,
* @param service the fully qualified name of the UNO service to add,
*/
public static void addImplementation(IUnoidlProject project, String uri, String service) {
Element components = null;
Document document = project.getComponentsDocument();
if (document != null) {
components = project.getComponentsElement(document);
}
if (components != null) {
Element component = getPythonComponent(project, document, components, uri);
if (component != null) {
if (addImplementation(project, document, component, uri, service)) {
project.writeComponentsFile(document);
}
}
}
}
/**
* remove a UNO service implementation from the list of the project ones.
*
* @param project the project where to remove the implementation
* @param uri the fully qualified file of the implementation to remove,
* eg: <code>org.libreoffice.comp.test.MyServiceImpl</code>
*/
public static void removeImplementation(IUnoidlProject project, String uri) {
boolean removed = false;
Document document = project.getComponentsDocument(false);
if (document != null) {
Element components = project.getComponentsElement(document);
if (components != null) {
Element component = getPythonComponent(project, document, components, uri, false);
if (component != null) {
components.removeChild(component);
removed = true;
}
}
}
if (removed) {
project.writeComponentsFile(document);
}
}
private static boolean addImplementation(IUnoidlProject project, Document document, Element component,
String uri, String service) {
boolean added = false;
setComponentUri(component, uri);
Element element = project.getImplementationElement(component, service);
if (element != null) {
added = project.addServiceElement(document, element, service);
} else {
element = project.createImplementation(document, component, service, service);
added = true;
}
// If an implementation has been added, we must remove any existing ones.
if (added) {
project.removeImplementationElements(component, element);
}
return added;
}
private static Element getPythonComponent(IUnoidlProject project, Document document,
Element components, String uri) {
return getPythonComponent(project, document, components, uri, true);
}
private static Element getPythonComponent(IUnoidlProject project, Document document,
Element components, String uri, boolean create) {
Element component = null;
NodeList nodes = components.getElementsByTagName("component"); //$NON-NLS-1$
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
if (isPythonComponent(element, uri)) {
component = element;
break;
}
}
}
if (component == null && create) {
component = createPythonComponent(project, document, components, uri);
}
return component;
}
private static Element createPythonComponent(IUnoidlProject project, Document document,
Element components, String uri) {
Element component = document.createElement("component"); //$NON-NLS-1$
component.setAttribute("loader", "com.sun.star.loader.Python"); //$NON-NLS-1$ //$NON-NLS-2$
setComponentUri(component, uri);
components.appendChild(component);
return component;
}
private static boolean isPythonComponent(Element component, String uri) {
return component.hasAttribute("loader") && //$NON-NLS-1$
component.hasAttribute("uri") && //$NON-NLS-1$
component.getAttribute("loader").equals("com.sun.star.loader.Python") && //$NON-NLS-1$ //$NON-NLS-2$
component.getAttribute("uri").equals(uri); //$NON-NLS-1$
}
private static void setComponentUri(Element component, String uri) {
component.setAttribute("uri", uri); //$NON-NLS-1$
}
}