diff --git a/java/maven.osgi/nbproject/project.xml b/java/maven.osgi/nbproject/project.xml index f29c4913bb9b..d60552adc981 100644 --- a/java/maven.osgi/nbproject/project.xml +++ b/java/maven.osgi/nbproject/project.xml @@ -122,14 +122,6 @@ 1.6 - - org.netbeans.modules.netbinox - - - - 1.33 - - org.netbeans.modules.projectapi diff --git a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/AccessQueryImpl.java b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/AccessQueryImpl.java index c24cd09bc8df..e561c351553d 100644 --- a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/AccessQueryImpl.java +++ b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/AccessQueryImpl.java @@ -19,10 +19,7 @@ package org.netbeans.modules.maven.osgi; -import java.lang.ref.WeakReference; -import java.util.List; import java.util.StringTokenizer; -import java.util.regex.Pattern; import org.netbeans.modules.maven.api.NbMavenProject; import org.netbeans.api.project.Project; import org.netbeans.modules.maven.api.PluginPropertyUtils; @@ -38,13 +35,12 @@ public class AccessQueryImpl implements AccessibilityQueryImplementation { private final Project prj; - private WeakReference> ref; private static final String DEFAULT_IMP = "*"; - + public AccessQueryImpl(Project prj) { this.prj = prj; } - + /** * * @param pkg @@ -60,10 +56,10 @@ public Boolean isPubliclyAccessible(FileObject pkg) { return check(name); } } - + return null; } - + private Boolean check(String value) { String[] exps = PluginPropertyUtils.getPluginPropertyList(prj, OSGiConstants.GROUPID_FELIX, OSGiConstants.ARTIFACTID_BUNDLE_PLUGIN, @@ -99,44 +95,44 @@ private Boolean check(String value) { } return result; } - - static boolean testPackagePatterns(String patterns, String value) { - boolean matches = false; + + static boolean testPackagePatterns(String patterns, String value) { + boolean matches = false; if (patterns != null) { - patterns = PackageDefinitionUtil.omitDirectives(patterns); - StringTokenizer tok = new StringTokenizer(patterns, " ,", false); //NOI18N + String onlyPackagesPatterns = PackageDefinitionUtil.omitDirectives(patterns); + StringTokenizer tok = new StringTokenizer(onlyPackagesPatterns, " ,", false); //NOI18N while (tok.hasMoreTokens() && !matches) { String token = tok.nextToken(); token = token.trim(); - if ("*".equals(token)) { //NOI18N - return true; - } - + if ("*".equals(token)) { //NOI18N + return true; + } + boolean recursive = false; - boolean exclusivePattern = false; - if (token.startsWith("!")) { - token = token.substring(1); - exclusivePattern = true; - } - if (token.endsWith("*")) { //NOI18N - // The following cases are tested with maven-bundle-plugin - // a.* or a* -> recursive - // a. -> non-recursive - token = token.substring(0, token.length() - "*".length()); //NOI18N - recursive = true; - if (token.endsWith(".")) { - // Removes the last dot also - token = token.substring(0, token.length() - 1); - } + boolean exclusivePattern = false; + if (token.startsWith("!")) { + token = token.substring(1); + exclusivePattern = true; + } + if (token.endsWith("*")) { //NOI18N + // The following cases are tested with maven-bundle-plugin + // a.* or a* -> recursive + // a. -> non-recursive + token = token.substring(0, token.length() - "*".length()); //NOI18N + recursive = true; + if (token.endsWith(".")) { + // Removes the last dot also + token = token.substring(0, token.length() - 1); + } + } + matches = recursive ? value.startsWith(token) : value.equals(token); + if (matches && exclusivePattern) { + // only excluding when it matches + matches = !matches; } - matches = recursive ? value.startsWith(token) : value.equals(token); - if (matches && exclusivePattern) { - // only excluding when it matches - matches = !matches; - } } } - return matches; - } + return matches; + } } diff --git a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/FelixPluginGrammarExtension.java b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/FelixPluginGrammarExtension.java index 47c3a4a43a35..dfb4c10c20e8 100644 --- a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/FelixPluginGrammarExtension.java +++ b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/FelixPluginGrammarExtension.java @@ -51,18 +51,18 @@ public class FelixPluginGrammarExtension implements GrammarExtensionProvider { }; @Override - @NonNull + @NonNull public List getDynamicCompletion(String path, HintContext hintCtx, Element parent) { //TODO also plugin/executions/execution/configuration should apply if (path.endsWith("plugins/plugin/configuration") && isFelixPlugin(hintCtx.getParentNode())) { //NOI18N - List result = new ArrayList(); + List result = new ArrayList<>(); result.add(new AbstractSchemaBasedGrammar.MyTextElement(OSGiConstants.PARAM_INSTRUCTIONS, hintCtx.getCurrentPrefix())); return result; } if (path.endsWith("plugins/plugin/configuration/" + OSGiConstants.PARAM_INSTRUCTIONS) && isFelixPlugin(hintCtx.getParentNode().getParentNode())) { //NOI18N - List result = new ArrayList(); + List result = new ArrayList<>(); for (String curInst : txtInstructions) { result.add(new AbstractSchemaBasedGrammar.MyTextElement(curInst, hintCtx.getCurrentPrefix())); } @@ -89,7 +89,7 @@ private static boolean isFelixPlugin (Node configNode) { Node curNode = pluginChildren.item(i); if ("groupId".equals(curNode.getNodeName())) { NodeList children = curNode.getChildNodes(); - if (children.getLength() > 0 && + if (children.getLength() > 0 && OSGiConstants.GROUPID_FELIX.equals(children.item(0).getNodeValue())) { felixGroupId = true; } else { @@ -98,7 +98,7 @@ private static boolean isFelixPlugin (Node configNode) { } if ("artifactId".equals(curNode.getNodeName())) { NodeList children = curNode.getChildNodes(); - if (children.getLength() > 0 && + if (children.getLength() > 0 && OSGiConstants.ARTIFACTID_BUNDLE_PLUGIN.equals(children.item(0).getNodeValue())) { felixArtifactId = true; } else { diff --git a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/ForeignClassBundlerImpl.java b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/ForeignClassBundlerImpl.java index d8bdfe3892bd..8a273fb66aa4 100644 --- a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/ForeignClassBundlerImpl.java +++ b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/ForeignClassBundlerImpl.java @@ -49,25 +49,26 @@ public class ForeignClassBundlerImpl implements ForeignClassBundler, ProjectProblemsProvider { // #179521 private static final ProjectProblem PROBLEM_REPORT = ProjectProblem.createWarning(PRBL_Name(), PRBL_DESC()); private static final RequestProcessor RP = new RequestProcessor(ForeignClassBundlerImpl.class); - + private final AtomicBoolean hasProblem = new AtomicBoolean(false); - + private final Project project; private boolean calculated = false; private boolean calculatedValue = false; + @SuppressWarnings({"this-escape"}) private final PropertyChangeSupport pchs = new PropertyChangeSupport(this); public ForeignClassBundlerImpl(Project p) { project = p; } - - @Override + + @Override public synchronized boolean preferSources() { if (calculated) { return calculatedValue; } - calculatedValue = calculateValue(); + calculatedValue = calculateValue(); calculated = true; return calculatedValue; } @@ -119,15 +120,12 @@ private boolean calculateValue() { } finally { if (newVal != oldVal) { hasProblem.set(newVal); - RP.post(new Runnable() { - @Override - public void run() { - pchs.firePropertyChange(ProjectProblemsProvider.PROP_PROBLEMS, null, null); - } + RP.post(() -> { + pchs.firePropertyChange(ProjectProblemsProvider.PROP_PROBLEMS, null, null); }); } } - //according to http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html default value is just + //according to http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html default value is just //project's own sources return true; } @@ -152,5 +150,5 @@ public Collection getProblems() { return hasProblem.get() ? Collections.singleton(PROBLEM_REPORT) : Collections.emptySet(); } - + } diff --git a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/Matcher.java b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/Matcher.java index c4ec74225174..8efb6bd20a36 100644 --- a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/Matcher.java +++ b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/Matcher.java @@ -35,7 +35,7 @@ * */ class Matcher { - + /** * Auxiliary class for each of the PATTERNs in the LIST. */ @@ -74,9 +74,9 @@ boolean matches(String packageName) { /** * Precompiled PATTERNs on the LIST. - */ + */ private final Item[] items; - + /** * Value to be returned when package is not matched by any of items. */ @@ -116,20 +116,16 @@ private static Pattern toPattern(String value) { for (int i = 0; i < l; ++i) { final char c = value.charAt(i); switch (c) { - case '.': - sb.append("\\."); - break; - case '*': + case '.' -> sb.append("\\."); + case '*' -> { sb.append(".*"); hasWildcards = true; - break; - case '?': + } + case '?' -> { sb.append(".?"); hasWildcards = true; - break; - default: - sb.append(c); - break; + } + default -> sb.append(c); } } if (hasWildcards) { @@ -149,10 +145,10 @@ private static Pattern toPattern(String value) { // use a simple equals test. return null; // No pattern needed. } - } + } Matcher(String pattern) { - List list = new ArrayList(); + List list = new ArrayList<>(); boolean unmatched = false; // Default for no items. if (pattern != null && !pattern.contains("${")) { String[] strItems = pattern.split(","); @@ -182,11 +178,11 @@ private static Pattern toPattern(String value) { } } } - items = list.toArray(new Item[0]); + items = list.toArray(Item[]::new); unmatchedValue = unmatched; } - - + + boolean matches(String packageName) { for (Item item : items) { if (item.matches(packageName)) { diff --git a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/OSGILookupProvider.java b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/OSGILookupProvider.java index 0c169c88c1fb..ba308913ec7c 100644 --- a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/OSGILookupProvider.java +++ b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/OSGILookupProvider.java @@ -21,7 +21,6 @@ package org.netbeans.modules.maven.osgi; import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -34,14 +33,15 @@ import org.netbeans.modules.maven.api.PluginPropertyUtils; import org.netbeans.spi.project.LookupProvider; import org.netbeans.spi.project.ui.RecommendedTemplates; -import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.lookup.AbstractLookup; import org.openide.util.lookup.InstanceContent; /** - * intentional manual implementation of lookupprovider. for packagings other then bundle but with bundle-maven-plugin configuration + * intentional manual implementation of lookupprovider. for packagings other + * then bundle but with bundle-maven-plugin configuration * we want to have some osgi related impls in the lookup. + * * @author mkleint */ @LookupProvider.Registration(projectType="org-netbeans-modules-maven") @@ -49,7 +49,7 @@ public class OSGILookupProvider implements LookupProvider { public OSGILookupProvider() { } - + @Override public Lookup createAdditionalLookup(Lookup baseContext) { final InstanceContent ic = new InstanceContent(); @@ -57,34 +57,25 @@ public Lookup createAdditionalLookup(Lookup baseContext) { assert prj != null; final AccessQueryImpl access = new AccessQueryImpl(prj); final ForeignClassBundlerImpl bundler = new ForeignClassBundlerImpl(prj); - final RecommendedTemplates templates = new RecommendedTemplates() { - @Override - public String[] getRecommendedTypes() { - return new String[] {"osgi"}; - } - }; + final RecommendedTemplates templates = () -> new String[] {"osgi"}; NbMavenProject nbprj = prj.getLookup().lookup(NbMavenProject.class); - nbprj.addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (NbMavenProject.PROP_PROJECT.equals(evt.getPropertyName())) { - checkContent(prj, ic, access, bundler, templates); - } + nbprj.addPropertyChangeListener((PropertyChangeEvent evt) -> { + if (NbMavenProject.PROP_PROJECT.equals(evt.getPropertyName())) { + checkContent(prj, ic, access, bundler, templates); } - }); checkContent(prj, ic, access, bundler, templates); return new AbstractLookup(ic); } - + private void checkContent(Project prj, InstanceContent ic, AccessQueryImpl access, ForeignClassBundlerImpl bundler, RecommendedTemplates templates) { NbMavenProject nbprj = prj.getLookup().lookup(NbMavenProject.class); String effPackaging = nbprj.getPackagingType(); - + boolean needToCheckFelixProjectTypes = true; - if(!nbprj.isMavenProjectLoaded()) { - // issue #262646 - // due to unfortunate ProjectManager.findPorjetc calls in awt, + if(!nbprj.isMavenProjectLoaded()) { + // issue #262646 + // due to unfortunate ProjectManager.findPorjetc calls in awt, // speed is essential during project init, so lets try to avoid // maven project loading if we can get the info faster from raw model. needToCheckFelixProjectTypes = false; @@ -92,7 +83,7 @@ private void checkContent(Project prj, InstanceContent ic, AccessQueryImpl acces try { model = nbprj.getRawModel(); } catch (ModelBuildingException ex) { - // whatever happend, we can't use the model, + // whatever happend, we can't use the model, // lets try to follow up with loading the maven project model = null; Logger.getLogger(OSGILookupProvider.class.getName()).log(Level.FINE, null, ex); @@ -106,7 +97,7 @@ private void checkContent(Project prj, InstanceContent ic, AccessQueryImpl acces break; } } - } + } } if(needToCheckFelixProjectTypes) { String[] types = PluginPropertyUtils.getPluginPropertyList(prj, OSGiConstants.GROUPID_FELIX, OSGiConstants.ARTIFACTID_BUNDLE_PLUGIN, "supportedProjectTypes", "supportedProjectType", /*"bundle" would not work for GlassFish parent POM*/null); diff --git a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/OSGIRecoPrivTemplates.java b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/OSGIRecoPrivTemplates.java index f584f09c439d..7a5f7d01ff68 100644 --- a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/OSGIRecoPrivTemplates.java +++ b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/OSGIRecoPrivTemplates.java @@ -29,7 +29,7 @@ */ @ProjectServiceProvider(service={RecommendedTemplates.class, PrivilegedTemplates.class}, projectType="org-netbeans-modules-maven/" + NbMavenProject.TYPE_OSGI) public class OSGIRecoPrivTemplates implements RecommendedTemplates, PrivilegedTemplates { - + private static final String[] OSGI_PRIVILEGED_NAMES = new String[] { "Templates/Classes/Class.java", // NOI18N "Templates/Classes/Package", // NOI18N @@ -49,14 +49,14 @@ public class OSGIRecoPrivTemplates implements RecommendedTemplates, PrivilegedTe "junit", // NOI18N "simple-files" // NOI18N }; - - + + public @Override String[] getRecommendedTypes() { return OSGI_TYPES; } - + public @Override String[] getPrivilegedTemplates() { return OSGI_PRIVILEGED_NAMES; } - + } diff --git a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/OSGiJarAccessibilityQueryImpl.java b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/OSGiJarAccessibilityQueryImpl.java index f73a16c25426..8be2436504aa 100644 --- a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/OSGiJarAccessibilityQueryImpl.java +++ b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/OSGiJarAccessibilityQueryImpl.java @@ -22,15 +22,12 @@ import java.awt.Image; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.WeakHashMap; import java.util.jar.Manifest; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.maven.artifact.Artifact; -import org.eclipse.osgi.util.ManifestElement; import org.netbeans.api.annotations.common.StaticResource; import org.netbeans.modules.maven.spi.nodes.DependencyTypeIconBadge; import org.netbeans.spi.java.queries.AccessibilityQueryImplementation; @@ -41,7 +38,7 @@ import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProviders; -import org.osgi.framework.BundleException; + import static org.netbeans.modules.maven.osgi.Bundle.*; /** @@ -49,34 +46,35 @@ * @author mkleint */ @ServiceProviders({ - @ServiceProvider(service = AccessibilityQueryImplementation.class), + @ServiceProvider(service = AccessibilityQueryImplementation.class), @ServiceProvider(service = DependencyTypeIconBadge.class) }) public class OSGiJarAccessibilityQueryImpl implements AccessibilityQueryImplementation, DependencyTypeIconBadge { private static final Logger LOG = Logger.getLogger(OSGiJarAccessibilityQueryImpl.class.getName()); private static final @StaticResource String BADGE = "org/netbeans/modules/maven/osgi/maven_osgi_badge.png"; - private static final String toolTip = " " //NOI18N + private static final String TOOLTIP = " " //NOI18N + Tooltip_manifest();//NOI18N - private final WeakHashMap> publicCache = new WeakHashMap>(); - private final List NOT_OSGIJAR = new ArrayList(); - + private final WeakHashMap> publicCache = new WeakHashMap<>(); + private final List NOT_OSGIJAR = new ArrayList<>(); + @Override + @SuppressWarnings("null") // relPath is runtime null checked in addition to assert public Boolean isPubliclyAccessible(FileObject pkg) { FileObject jarFile = FileUtil.getArchiveFile(pkg); boolean notOSGi = true; if (jarFile != null) { FileObject jarRoot = FileUtil.getArchiveRoot(jarFile); synchronized (publicCache) { - List pub = publicCache.get(jarRoot); - + List pub = publicCache.get(jarRoot); + if (pub != null) { if (pub == NOT_OSGIJAR) { return null; } String relPath = FileUtil.getRelativePath(jarRoot, pkg); assert relPath != null : "null path for : " + jarRoot + ", " + pkg; - if(relPath == null) { + if (relPath == null) { LOG.log(Level.WARNING, "null path for : {0}, {1}", new Object[]{jarRoot, pkg}); return Boolean.FALSE; } @@ -87,13 +85,12 @@ public Boolean isPubliclyAccessible(FileObject pkg) { if (manifest != null) { try { Manifest mf = new Manifest(manifest.getInputStream()); - List pub = null; + List pub = null; String exportPack = mf.getMainAttributes().getValue(OSGiConstants.EXPORT_PACKAGE); if (exportPack != null) { try { - ManifestElement[] mans = ManifestElement.parseHeader(OSGiConstants.EXPORT_PACKAGE, exportPack); - pub = Arrays.asList(mans); - } catch (BundleException ex) { + pub = splitExportPackages(exportPack); + } catch (RuntimeException ex) { Exceptions.printStackTrace(ex); } } @@ -116,16 +113,16 @@ public Boolean isPubliclyAccessible(FileObject pkg) { } } synchronized (publicCache) { - publicCache.put(jarRoot, notOSGi ? NOT_OSGIJAR : Collections.emptyList()); + publicCache.put(jarRoot, notOSGi ? NOT_OSGIJAR : List.of()); } } return notOSGi ? null : Boolean.FALSE; - + } - private Boolean check(List pub, String packageName) { - for (ManifestElement p : pub) { - if (packageName.equals(p.getValue())) { + private Boolean check(List pub, String packageName) { + for (String p : pub) { + if (packageName.equals(p)) { return Boolean.TRUE; } } @@ -137,8 +134,8 @@ public Image getBadgeIcon(FileObject jarFile, Artifact art) { if (jarFile != null && FileUtil.isArchiveFile(jarFile)) { FileObject jarRoot = FileUtil.getArchiveRoot(jarFile); synchronized (publicCache) { - List pub = publicCache.get(jarRoot); - + List pub = publicCache.get(jarRoot); + if (pub != null) { if (pub == NOT_OSGIJAR) { return null; @@ -150,7 +147,6 @@ public Image getBadgeIcon(FileObject jarFile, Artifact art) { if (manifest != null) { try { Manifest mf = new Manifest(manifest.getInputStream()); - List pub = null; String name = mf.getMainAttributes().getValue(OSGiConstants.BUNDLE_SYMBOLIC_NAME); if (name != null) { return getIcon(); @@ -163,12 +159,85 @@ public Image getBadgeIcon(FileObject jarFile, Artifact art) { publicCache.put(jarRoot, NOT_OSGIJAR); } } - return null; + return null; } @NbBundle.Messages("Tooltip_manifest=Contains OSGi manifest headers") private Image getIcon() { - return ImageUtilities.addToolTipToImage(ImageUtilities.loadImage(BADGE), toolTip); + return ImageUtilities.addToolTipToImage(ImageUtilities.loadImage(BADGE), TOOLTIP); } + /** + * OSGI-Specification declares: + * + *
+     * Export-Package  ::= export ( ',' export)*
+     * export          ::= package-names ( ';' parameter )*
+     * package-names   ::= package-name                // See 1.3.2
+     *                   ( ';' package-name )*
+     * 
+ * + * @param exportPkg String formatted according to Export-Package + * @return list of package-name entries + */ + // Same implementation is used in org.netbeans.core.netigso.Netigso and + // org.netbeans.modules.maven.osgi.OSGiJarAccessibilityQueryImpl copied to + // not introduce module dependencies. Tests are in Netigso, when updated, + // update both places! + static List splitExportPackages(String exportPkg) { + List exports = new ArrayList<>(); + StringBuilder buffer = new StringBuilder(); + boolean inQuotedString = false; + for (int i = 0; i < exportPkg.length(); i++) { + char nextChar = exportPkg.charAt(i); + switch(nextChar) { + case '"' -> { + inQuotedString = ! inQuotedString; + buffer.append(nextChar); + } + case ',' -> { + if (inQuotedString) { + buffer.append(nextChar); + } else { + exports.add(buffer.toString()); + buffer.setLength(0); + } + } + case '\\' -> { + buffer.append(nextChar); + if (inQuotedString) { + if((i + 1) == exportPkg.length()) { + throw new IllegalStateException("Invalid escape sequence"); + } + nextChar = exportPkg.charAt(i + 1); + i++; + if (nextChar == '"' || nextChar == '\\') { + buffer.append(nextChar); + } else { + throw new IllegalStateException("Invalid escape sequence"); + } + } + } + default -> buffer.append(nextChar); + } + } + if(! buffer.isEmpty()){ + exports.add(buffer.toString()); + } + List packageNames = new ArrayList<>(); + // Each export statement can hold multiple package names separated by + // semicolon, so split on semicolon. package-name and parameter are + // discerned based on the presence of a equals character. A package-name + // must not contain it, a parameter must. + for(String export: exports) { + for(String packageCandiate: export.split(";")) { + // package-name list ends with first parameter + if(packageCandiate.contains("=")) { + break; + } + packageNames.add(packageCandiate); + } + } + return packageNames; + } } diff --git a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/customizer/FelixExportPersister.java b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/customizer/FelixExportPersister.java index 1678c4b1fa00..a31a6a2ae5a0 100644 --- a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/customizer/FelixExportPersister.java +++ b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/customizer/FelixExportPersister.java @@ -51,10 +51,10 @@ public class FelixExportPersister implements SelectedItemsTablePersister { private final Project project; private ModelOperation operation; private ModelOperation defaultOperation; - + private boolean isDefined = false; - private SortedMap defaultValue; + private final SortedMap defaultValue; public FelixExportPersister (Project project, ModelHandle2 handle) { this.project = project; @@ -79,17 +79,17 @@ public FelixExportPersister (Project project, ModelHandle2 handle) { privateInstruction = privates[0]; } - Map instructions = new HashMap(2); + Map instructions = new HashMap<>(2); instructions.put(InstructionsConverter.EXPORT_PACKAGE, exportInstruction); instructions.put(InstructionsConverter.PRIVATE_PACKAGE, privateInstruction); defaultValue = InstructionsConverter.computeExportList(instructions, project); } - + public boolean isIsDefined() { return isDefined; } - + @Override public SortedMap read() { @@ -101,9 +101,9 @@ public void write(SortedMap selItems) { if (operation != null) { handle.removePOMModification(operation); } - + final Map exportIns = InstructionsConverter.computeExportInstructions(selItems, project); - operation = new ModelOperation() { + operation = new ModelOperation<>() { @Override public void performOperation(POMModel pomModel) { @@ -143,7 +143,7 @@ public void performOperation(POMModel pomModel) { createPOMExtensibilityElement(new QName(OSGiConstants.PARAM_INSTRUCTIONS)); config.addExtensibilityElement(instructionsEl); } - + POMExtensibilityElement exportEl = ModelUtils.getOrCreateChild(instructionsEl, OSGiConstants.EXPORT_PACKAGE, pomModel); POMExtensibilityElement privateEl = ModelUtils.getOrCreateChild(instructionsEl, OSGiConstants.PRIVATE_PACKAGE, pomModel); @@ -162,7 +162,7 @@ void setDefault(boolean def) { } if (defaultOperation == null) { defaultOperation = new ModelOperation() { - + @Override public void performOperation(POMModel pomModel) { Build build = pomModel.getProject().getBuild(); @@ -191,7 +191,7 @@ public void performOperation(POMModel pomModel) { } } } - + private POMExtensibilityElement findInstructions(PluginContainer cont) { Plugin felixPlugin = cont.findPluginById(OSGiConstants.GROUPID_FELIX, OSGiConstants.ARTIFACTID_BUNDLE_PLUGIN); if (felixPlugin != null) { @@ -206,7 +206,7 @@ private POMExtensibilityElement findInstructions(PluginContainer cont) { } } return null; - } + } private void removeExportPrivate(POMExtensibilityElement instructionsEl) { if (instructionsEl != null) { @@ -221,7 +221,7 @@ private void removeExportPrivate(POMExtensibilityElement instructionsEl) { } } }; - + } handle.addPOMModification(defaultOperation); } else { diff --git a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/customizer/InstructionsConverter.java b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/customizer/InstructionsConverter.java index 7312fa3d7d1a..588ccb183595 100644 --- a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/customizer/InstructionsConverter.java +++ b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/customizer/InstructionsConverter.java @@ -44,7 +44,7 @@ public final class InstructionsConverter { public static final Integer PRIVATE_PACKAGE = 2; public static Map computeExportInstructions (Map items, Project project) { - Map instructionsMap = new HashMap(2); + Map instructionsMap = new HashMap<>(2); StringBuilder exportIns = new StringBuilder(); boolean isFirst = true; for (Entry entry : items.entrySet()) { @@ -78,7 +78,7 @@ public static Map computeExportInstructions (Map computeExportList (Map exportInstructions, Project project) { - SortedMap pkgMap = new TreeMap(); + SortedMap pkgMap = new TreeMap<>(); SortedSet pkgNames = FileUtilities.getPackageNames(project); for (String name : pkgNames) { pkgMap.put(name, Boolean.FALSE); diff --git a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/templates/ActivatorIterator.java b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/templates/ActivatorIterator.java index a04aee6eb1aa..49ab65db7f74 100644 --- a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/templates/ActivatorIterator.java +++ b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/templates/ActivatorIterator.java @@ -63,21 +63,22 @@ * * @author mkleint */ -@TemplateRegistration(folder="OSGi", position=100, content="Activator.java.template", scriptEngine="freemarker", displayName="#template.activator", iconBase="org/netbeans/modules/maven/osgi/templates/new_OSGi_file_16.png", description="new_OSGi_activator.html", category="osgi") +@TemplateRegistration( + folder="OSGi", + position=100, + content="Activator.java.template", + scriptEngine="freemarker", + displayName="#template.activator", + iconBase="org/netbeans/modules/maven/osgi/templates/new_OSGi_file_16.png", + description="new_OSGi_activator.html", + category="osgi" +) @Messages("template.activator=Bundle Activator") public class ActivatorIterator implements TemplateWizard.AsynchronousInstantiatingIterator { - private static final Logger LOG = Logger.getLogger(ActivatorIterator.class.getName()); - + // You should define what panels you want to use here: protected List> createPanels (Project project, TemplateWizard wiz) { Sources sources = ProjectUtils.getSources(project); - DataFolder targetFolder=null; - try { - targetFolder = wiz.getTargetFolder(); - } - catch (IOException ex) { - targetFolder = DataFolder.findFolder(project.getProjectDirectory()); - } return Collections.>singletonList( JavaTemplates.createPackageChooser(project, sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA)) @@ -94,13 +95,13 @@ public Set instantiate () throws IOException/*, IllegalStateExceptio // More advanced wizards can create multiple objects from template // (return them all in the result of this method), populate file // contents on the fly, etc. - + org.openide.filesystems.FileObject dir = Templates.getTargetFolder( wiz ); DataFolder df = DataFolder.findFolder( dir ); - + FileObject template = Templates.getTemplate( wiz ); - - DataObject dTemplate = DataObject.find( template ); + + DataObject dTemplate = DataObject.find( template ); final DataObject dobj = dTemplate.createFromTemplate( df, Templates.getTargetName( wiz ) ); //this part might be turned pluggable once we have also ant based osgi projects. if.. @@ -110,15 +111,10 @@ public Set instantiate () throws IOException/*, IllegalStateExceptio final NbMavenProject prj = project.getLookup().lookup(NbMavenProject.class); if (prj != null) { - Utilities.performPOMModelOperations(project.getProjectDirectory().getFileObject("pom.xml"), - Collections.>singletonList( - new ModelOperation() { - @Override - public void performOperation(POMModel model) { - addActivator(prj, model, path); - } - } - )); + Utilities.performPOMModelOperations( + project.getProjectDirectory().getFileObject("pom.xml"), + List.>of((model) -> addActivator(prj, model, path)) + ); } return Collections.singleton(dobj); @@ -141,7 +137,7 @@ private void addActivator(NbMavenProject prj, POMModel mdl, String path) { plugin = mdl.getFactory().createPlugin(); plugin.setGroupId(OSGiConstants.GROUPID_FELIX); plugin.setArtifactId(OSGiConstants.ARTIFACTID_BUNDLE_PLUGIN); - String ver = PluginPropertyUtils.getPluginVersion(prj.getMavenProject(), + String ver = PluginPropertyUtils.getPluginVersion(prj.getMavenProject(), OSGiConstants.GROUPID_FELIX, OSGiConstants.ARTIFACTID_BUNDLE_PLUGIN); if (ver == null) { //not defined in resolved project, set version. @@ -183,13 +179,14 @@ private void addActivator(NbMavenProject prj, POMModel mdl, String path) { } // --- The rest probably does not need to be touched. --- - + private transient int index; private transient List> panels; private transient TemplateWizard wiz; + @SuppressWarnings("unused") private static final long serialVersionUID = -7586964579556513549L; - + // You can keep a reference to the TemplateWizard which can // provide various kinds of useful information such as // the currently selected target name. @@ -200,15 +197,15 @@ public void initialize (WizardDescriptor wiz) { index = 0; Project project = Templates.getProject( wiz ); panels = createPanels (project,this.wiz); - + // Creating steps. Object prop = wiz.getProperty (WizardDescriptor.PROP_CONTENT_DATA); // NOI18N String[] beforeSteps = null; - if (prop instanceof String[]) { - beforeSteps = (String[])prop; + if (prop instanceof String[] strings) { + beforeSteps = strings; } String[] steps = createSteps (beforeSteps, panels); - + for (int i = 0; i < panels.size(); i++) { Component c = panels.get(i).getComponent (); if (steps[i] == null) { @@ -217,10 +214,9 @@ public void initialize (WizardDescriptor wiz) { // chooser to appear in the list of steps. steps[i] = c.getName (); } - if (c instanceof JComponent) { // assume Swing components - JComponent jc = (JComponent) c; + if (c instanceof JComponent jc) { // assume Swing components // Step #. - jc.putClientProperty(WizardDescriptor.PROP_CONTENT_SELECTED_INDEX, Integer.valueOf(i)); + jc.putClientProperty(WizardDescriptor.PROP_CONTENT_SELECTED_INDEX, i); // Step name (actually the whole list for reference). jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DATA, steps); } @@ -242,7 +238,7 @@ public void uninitialize (WizardDescriptor wiz) { public String name () { return TITLE_x_of_y(index + 1, panels.size()); } - + @Override public boolean hasNext () { return index < panels.size() - 1; @@ -269,7 +265,7 @@ public void previousPanel () { public WizardDescriptor.Panel current () { return panels.get(index); } - + // If nothing unusual changes in the middle of the wizard, simply: @Override public final void addChangeListener (ChangeListener l) {} diff --git a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/templates/BundleWizard.java b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/templates/BundleWizard.java index d6d99785b3ae..de5b70f32a50 100644 --- a/java/maven.osgi/src/org/netbeans/modules/maven/osgi/templates/BundleWizard.java +++ b/java/maven.osgi/src/org/netbeans/modules/maven/osgi/templates/BundleWizard.java @@ -26,8 +26,14 @@ import static org.netbeans.modules.maven.osgi.templates.Bundle.*; public class BundleWizard { - - @TemplateRegistration(folder=ArchetypeWizards.TEMPLATE_FOLDER, position=290, displayName="#template.project.OSGi", iconBase="org/netbeans/modules/maven/osgi/maven_osgi_16.png", description="OSGiDescription.html") + + @TemplateRegistration( + folder=ArchetypeWizards.TEMPLATE_FOLDER, + position=290, + displayName="#template.project.OSGi", + iconBase="org/netbeans/modules/maven/osgi/maven_osgi_16.png", + description="OSGiDescription.html" + ) @Messages("template.project.OSGi=OSGi Bundle") public static WizardDescriptor.InstantiatingIterator create() { return ArchetypeWizards.definedArchetype("org.codehaus.mojo.archetypes", "osgi-archetype", "1.4", null, template_project_OSGi()); diff --git a/platform/core.netigso/src/org/netbeans/core/netigso/Netigso.java b/platform/core.netigso/src/org/netbeans/core/netigso/Netigso.java index 61e6de2d4249..25d5220e8923 100644 --- a/platform/core.netigso/src/org/netbeans/core/netigso/Netigso.java +++ b/platform/core.netigso/src/org/netbeans/core/netigso/Netigso.java @@ -293,7 +293,7 @@ protected Set createLoader(ModuleInfo m, ProxyClassLoader pcl, File jar) } if (exported instanceof String) { for (String p : splitExportPackages(exported.toString())) { - pkgs.add(extractBundleName(p)); + pkgs.add(p); } } } finally { @@ -802,8 +802,25 @@ public final byte[] patchBC(ClassLoader l, String className, ProtectionDomain pd return patchByteCode(l, className, pd, arr); } + /** + * OSGI-Specification declares: + * + *
+     * Export-Package  ::= export ( ',' export)*
+     * export          ::= package-names ( ';' parameter )*
+     * package-names   ::= package-name                // See 1.3.2
+     *                   ( ';' package-name )*
+     * 
+ * + * @param exportPkg String formatted according to Export-Package + * @return list of package-name entries + */ + // Same implementation is used in org.netbeans.core.netigso.Netigso and + // org.netbeans.modules.maven.osgi.OSGiJarAccessibilityQueryImpl copied to + // not introduce module dependencies. Tests are in Netigso, when updated, + // update both places! static List splitExportPackages(String exportPkg) { - List elements = new ArrayList<>(); + List exports = new ArrayList<>(); StringBuilder buffer = new StringBuilder(); boolean inQuotedString = false; for (int i = 0; i < exportPkg.length(); i++) { @@ -817,7 +834,7 @@ static List splitExportPackages(String exportPkg) { if (inQuotedString) { buffer.append(nextChar); } else { - elements.add(buffer.toString()); + exports.add(buffer.toString()); buffer.setLength(0); } } @@ -840,9 +857,23 @@ static List splitExportPackages(String exportPkg) { } } if(! buffer.isEmpty()){ - elements.add(buffer.toString()); + exports.add(buffer.toString()); + } + List packageNames = new ArrayList<>(); + // Each export statement can hold multiple package names separated by + // semicolon, so split on semicolon. package-name and parameter are + // discerned based on the presence of a equals character. A package-name + // must not contain it, a parameter must. + for(String export: exports) { + for(String packageCandiate: export.split(";")) { + // package-name list ends with first parameter + if(packageCandiate.contains("=")) { + break; + } + packageNames.add(packageCandiate); + } } - return elements; + return packageNames; } } diff --git a/platform/core.netigso/test/unit/src/org/netbeans/core/netigso/NetigsoTest.java b/platform/core.netigso/test/unit/src/org/netbeans/core/netigso/NetigsoTest.java index c440c9a9482a..e0ffe14d713d 100644 --- a/platform/core.netigso/test/unit/src/org/netbeans/core/netigso/NetigsoTest.java +++ b/platform/core.netigso/test/unit/src/org/netbeans/core/netigso/NetigsoTest.java @@ -223,17 +223,24 @@ public void testSplitExportPackages() { List result = Netigso.splitExportPackages(exportPkgs); assertEquals(4, result.size()); assertEquals("a.b", result.get(0)); - assertEquals("a.b.c;version=\"1.0.0\";uses:=\"x.y.z,x.y.z.k\"", result.get(1)); - assertEquals("a.b.c.d;version=\"1.0.0\"", result.get(2)); - assertEquals("a.b.c.e;version=\"1.0.0\";uses:=\"x.y.z\"", result.get(3)); + assertEquals("a.b.c", result.get(1)); + assertEquals("a.b.c.d", result.get(2)); + assertEquals("a.b.c.e", result.get(3)); // Test that the \" are ignored. exportPkgs = "x.y.z,a.b.c;a=\"\\\"\",d.e.f"; result = Netigso.splitExportPackages(exportPkgs); assertEquals(3, result.size()); assertEquals("x.y.z", result.get(0)); - assertEquals("a.b.c;a=\"\\\"\"", result.get(1)); + assertEquals("a.b.c", result.get(1)); assertEquals("d.e.f", result.get(2)); } + public void testSplitExportMultiPackagePackages() { + String exportPkgs = "com.acme.foo;com.acme.bar;version=1.23"; + List result = Netigso.splitExportPackages(exportPkgs); + assertEquals(2, result.size()); + assertEquals("com.acme.foo", result.get(0)); + assertEquals("com.acme.bar", result.get(1)); + } }