# HG changeset patch # Parent b1bd1b2a86e4d6e504ea4747c085d8b908003de5 hinter to MIMEResolver.Registration diff --git a/apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/DataObjectRegistrationHinter.java b/apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/DataObjectRegistrationHinter.java --- a/apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/DataObjectRegistrationHinter.java +++ b/apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/DataObjectRegistrationHinter.java @@ -73,6 +73,7 @@ import com.sun.source.tree.ModifiersTree; import com.sun.source.tree.NewArrayTree; import com.sun.source.tree.Tree; +import org.openide.filesystems.FileStateInvalidException; /** * #207219: {@code DataObject.Registration} conversion. @@ -117,30 +118,10 @@ String actionsMime = Utility.getMimeTypeFromActionsPath(file.getPath()); // // try get DataObject / DataObject.Factory available in this project - Map> visibleLoaderFactories = new HashMap>(); + Map> visibleLoaderFactories = Utility.getVisibleLoader(ctx, file); FileObject startingPath = file.getFileSystem().findResource(LOADERS_FOLDER); if (startingPath != null) { - for (FileObject aLoadersFileObject : NbCollections.iterable(startingPath.getChildren(true))) { - if (aLoadersFileObject.getPath().contains(FACTORIES_FOLDER)) { // its a factory - final Object instanceCreate = ctx.instanceAttribute(aLoadersFileObject); - if (instanceCreate != null) { - - if (!METHOD_DOPOOL_FACTORY.equals(instanceCreate)) { - - String ic = instanceCreate.toString(); - - if (visibleLoaderFactories.containsKey(ic)) { - visibleLoaderFactories.get(ic).add(Utility.getMimeTypeFromFactoryPath(aLoadersFileObject.getPath())); - } else { - List mime = new LinkedList(); - mime.add(Utility.getMimeTypeFromFactoryPath(aLoadersFileObject.getPath())); - visibleLoaderFactories.put(ic, mime); - } - } - } - } - } if (visibleLoaderFactories.isEmpty()) { ctx.addHint(Severity.VERIFIER, DataObjectRegistrationHinter_no_DataObject()); } else { @@ -490,5 +471,32 @@ private static String getMimeTypeFromActionsPath(String path) { return getMime(path, ACTIONS_FOLDER); } + + protected static Map> getVisibleLoader(final Context ctx, final FileObject file) throws FileStateInvalidException { + Map> visibleLoaderFactories = new HashMap>(); + FileObject startingPath = file.getFileSystem().findResource(LOADERS_FOLDER); + for (FileObject aLoadersFileObject : NbCollections.iterable(startingPath.getChildren(true))) { + if (aLoadersFileObject.getPath().contains(FACTORIES_FOLDER)) { // its a factory + + final Object instanceCreate = ctx.instanceAttribute(aLoadersFileObject); + if (instanceCreate != null) { + + if (!METHOD_DOPOOL_FACTORY.equals(instanceCreate)) { + + String ic = instanceCreate.toString(); + + if (visibleLoaderFactories.containsKey(ic)) { + visibleLoaderFactories.get(ic).add(Utility.getMimeTypeFromFactoryPath(aLoadersFileObject.getPath())); + } else { + List mime = new LinkedList(); + mime.add(Utility.getMimeTypeFromFactoryPath(aLoadersFileObject.getPath())); + visibleLoaderFactories.put(ic, mime); + } + } + } + } + } + return visibleLoaderFactories; + } } } diff --git a/apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/Hinter.java b/apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/Hinter.java --- a/apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/Hinter.java +++ b/apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/Hinter.java @@ -323,6 +323,55 @@ } } + + public void findAndModifyMultipleDeclaration(Map mappedDeclarations) throws IOException { + for (Map.Entry aDeclaration : mappedDeclarations.entrySet()) { + final Object instanceAttribute = aDeclaration.getKey(); + final ModifyDeclarationTask task = aDeclaration.getValue(); + + FileObject java = findDeclaringSource(instanceAttribute); + if (java == null) { + DialogDisplayer.getDefault().notify(new Message(Hinter_missing_instance_class(instanceAttribute), NotifyDescriptor.WARNING_MESSAGE)); + return; + } + JavaSource js = JavaSource.forFileObject(java); + if (js == null) { + throw new IOException("No source info for " + java); + } + js.runModificationTask(new Task() { + + public @Override + void run(WorkingCopy wc) throws Exception { + wc.toPhase(JavaSource.Phase.RESOLVED); + if (DataObject.find(layer.getLayerFile()).isModified()) { // #207077 + DialogDisplayer.getDefault().notify(new Message(Hinter_do_not_edit_layer(), NotifyDescriptor.WARNING_MESSAGE)); + return; + } + Element decl = findDeclaration(wc, instanceAttribute); + if (decl == null) { + DialogDisplayer.getDefault().notify(new Message(Hinter_missing_instance_class(instanceAttribute), NotifyDescriptor.WARNING_MESSAGE)); + return; + } + ModifiersTree mods; + if (decl.getKind() == ElementKind.CLASS) { + mods = wc.getTrees().getTree((TypeElement) decl).getModifiers(); + } else { + mods = wc.getTrees().getTree((ExecutableElement) decl).getModifiers(); + } + task.run(wc, decl, mods); + } + }).commit(); + SaveCookie sc = DataObject.find(java).getLookup().lookup(SaveCookie.class); + if (sc != null) { + sc.save(); + } + } + this.delete(file()); + saveLayer(); + + } + + /** * Tries to find the instance associated with a file. * If it is a folder, or not a {@code *.instance} file, null is returned. diff --git a/apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/MIMEResolverRegistrationHinter.java b/apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/MIMEResolverRegistrationHinter.java new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/MIMEResolverRegistrationHinter.java @@ -0,0 +1,614 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2012 Sun Microsystems, Inc. + */ +package org.netbeans.modules.apisupport.hints; + +import com.sun.source.tree.ModifiersTree; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.lang.model.element.Element; +import org.netbeans.api.java.classpath.ClassPath; +import org.netbeans.api.java.source.GeneratorUtilities; +import org.netbeans.api.java.source.WorkingCopy; +import static org.netbeans.modules.apisupport.hints.Bundle.*; +import org.netbeans.spi.editor.hints.ChangeInfo; +import org.netbeans.spi.editor.hints.Fix; +import org.netbeans.spi.editor.hints.Severity; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.MIMEResolver; +import org.openide.filesystems.URLMapper; +import org.openide.util.Exceptions; +import org.openide.util.NbBundle.Messages; +import org.openide.util.NbCollections; +import org.openide.util.lookup.ServiceProvider; +import org.openide.xml.EntityCatalog; +import org.openide.xml.XMLUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * + * #207960: convert MimeResolver + */ +@ServiceProvider(service = Hinter.class) +public class MIMEResolverRegistrationHinter implements Hinter { + + public static final String ACTIONS_FOLDER = "Actions"; //NOI18N + public static final String METHOD_DOPOOL_FACTORY = "method:org.openide.loaders.DataLoaderPool.factory"; //NOI18N + private static final String LOADERS_FOLDER = "Loaders/"; //NOI18N + private static final String FACTORIES_FOLDER = "Factories"; //NOI18N + private static final String SERVICES_MIME_RESOLVER = "Services/MIMEResolver"; //NOI18N + + @Override + @Messages({"MIMEResolverRegistrationHinter.noTarget=Cannot find a reasonable target for refactory", + "MIMEResolverRegistrationHinter.urlInvalid=URL not valid", "MIMEResolverRegistrationHinter.allInOne=into respective loader"}) + public void process(final Context ctx) throws Exception { + final FileObject file = ctx.file(); + final Object instanceCreate = ctx.instanceAttribute(file); + // cannot be folder + if (!file.isData()) { + return; + } + // must start with Services/MimeResolver + if (file.getPath().startsWith(SERVICES_MIME_RESOLVER)) { + if (checkAttributes(file, ctx)) { + if (annotationsMIMEResolverAvailable(ctx)) { + Map> visibleTarget = DataObjectRegistrationHinter.Utility.getVisibleLoader(ctx, file); + if (visibleTarget.isEmpty()) { + ctx.addHint(Severity.ERROR, MIMEResolverRegistrationHinter_noTarget()); + } else { + List fixes = new ArrayList(); // prepare list of fixes +// get information for strategy + final String url = (String) file.getAttribute("WritableXMLFileSystem.url"); //NOI18N + if (url == null && file.getSize() > 0) { + // XXX cannot handle inline content + ctx.addHint(Severity.WARNING, MIMEResolverRegistrationHinter_urlInvalid()); + return; + } + + if (url != null) { + FileObject xmlMimeFile = null; + URI u = new URI(url); + if (!u.isAbsolute()) { + URL[] layers = (URL[]) file.getAttribute("layers"); //NOI18N + assert layers != null && layers.length == 1; + FileObject layer = URLMapper.findFileObject(layers[0]); + if (layer != null) { + ClassPath src = ClassPath.getClassPath(layer, ClassPath.SOURCE); + String path = src.getResourceName(layer); + if (path != null) { + u = new URI("nbres", "/" + path, null).resolve(u); //NOI18N //NOI18N + } + xmlMimeFile = src.findResource("/" + u.getPath()); //NOI18N + } + } + + MIMEResolverStrategyManager sm = null; + if (xmlMimeFile != null) { + sm = new MIMEResolverStrategyManager(xmlMimeFile.toURL()); + } + + boolean allLoaderAccessible = false; + if (sm != null && !sm.isUseComplex()) { + // warn for use NameSpaceRegistration + // all mimetype at once + final Map modifications = sm.checkLoaderAccessibility(visibleTarget, ctx); + allLoaderAccessible = !modifications.isEmpty(); + + if (allLoaderAccessible) { + ctx.addHint(Severity.WARNING, ctx.standardAnnotationDescription(), new Fix() { + + @Override + public String getText() { + return ctx.standardAnnotationFixDescription() + " " + MIMEResolverRegistrationHinter_allInOne(); //NOI18N + } + + @Override + public ChangeInfo implement() throws Exception { + ctx.findAndModifyMultipleDeclaration(modifications); + return null; + } + }); + } + + } + if (sm == null || !allLoaderAccessible || sm.isUseComplex()) { + for (Map.Entry> loader : visibleTarget.entrySet()) { // + StringBuilder sbMime = new StringBuilder(); + for (String aMime : loader.getValue()) { + sbMime.append(aMime); + sbMime.append(","); //NOI18N + } + sbMime.deleteCharAt(sbMime.length() - 1); + + String fname = loader.getKey().substring(loader.getKey().lastIndexOf(".") + 1) + ".java"; //NOI18N + final String text = DataObjectRegistrationHinter_fix_special(fname, sbMime); + final String fixParam = loader.getKey(); + + fixes.add(new Fix() { + + @Override + public String getText() { + return ctx.standardAnnotationFixDescription() + " " + text; //NOI18N + } + + @Override + public ChangeInfo implement() throws Exception { + ctx.findAndModifyDeclaration(fixParam, new RegisterMIMEGenericResolver(ctx, url)); + return null; + } + }); + } + if (!fixes.isEmpty()) { + ctx.addHint(Severity.WARNING, ctx.standardAnnotationDescription(), fixes.toArray(new Fix[fixes.size()])); + + } + } + } + } + } + } + } + } + + @Messages("MIMEResolverRegistrationHinter.missing_dep=You must add a dependency on org.openide.filesystems (7.58+) before using this fix.") + private boolean annotationsMIMEResolverAvailable(Context ctx) { + if (ctx.canAccess(MIMEResolver.Registration.class.getName()) + && ctx.canAccess(MIMEResolver.ExtensionRegistration.class.getName()) + && ctx.canAccess(MIMEResolver.NamespaceRegistration.class.getName())) { + return true; + } else { + DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(MIMEResolverRegistrationHinter_missing_dep(), NotifyDescriptor.WARNING_MESSAGE)); + return false; + } + } + + @Messages({ + "# {0} - file attribute name", "MIMEResolverRegistrationHinter_unrecognized_attr=Unrecognized MimeResolver attribute: {0}", + "MIMEResolverRegistrationHinter.pleaseConvert=Please convert to displayName to be able to use MimeResolver hinter"}) + private boolean checkAttributes(FileObject file, Context ctx) { + boolean attributesCompatible = true; + for (String attr : NbCollections.iterable(file.getAttributes())) { + if (!attr.matches("position|displayName|SystemFileSystem.localizingBundle")) { //NOI18N + + ctx.addHint(Severity.WARNING, MIMEResolverRegistrationHinter_unrecognized_attr(attr)); + attributesCompatible = false; + } + } + if (file.getAttribute("literal:SystemFileSystem.localizingBundle") != null) { //NOI18N + attributesCompatible = false; + ctx.addHint(Severity.HINT, MIMEResolverRegistrationHinter_pleaseConvert()); + } + return attributesCompatible; + } + + private static class RegisterMIMEGenericResolver implements Context.ModifyDeclarationTask { + + private static final String MIMERESOLVER_REGISTRATION = "org.openide.filesystems.MIMEResolver.Registration"; //NOI18N + private final Context ctx; + private String url; + + public RegisterMIMEGenericResolver(Context ctx, String url) { + this.ctx = ctx; + this.url = url; + } + + @Override + public void run(WorkingCopy wc, Element declaration, ModifiersTree modifiers) throws Exception { + Map params = new HashMap(); + FileObject file = ctx.file(); + String displayName = ctx.bundlevalue(file.getAttribute("literal:displayName"), declaration); //NOI18N + + if (displayName == null) { + // checkAttributes method tries to warn user to avoid this fallback + // unaware if fix can be chained + displayName = "#TODO"; //NOI18N + } + params.put("position", file.getAttribute("position")); //NOI18N + params.put("displayName", displayName); //NOI18N + if (url != null) { + URI u = new URI(url); + if (!u.isAbsolute()) { + URL[] layers = (URL[]) file.getAttribute("layers"); //NOI18N + assert layers != null && layers.length == 1; + FileObject layer = URLMapper.findFileObject(layers[0]); + if (layer != null) { + ClassPath src = ClassPath.getClassPath(layer, ClassPath.SOURCE); + String path = src.getResourceName(layer); + if (path != null) { + u = new URI("nbres", "/" + path, null).resolve(u); //NOI18N //NOI18N + } + } + } + if (u.getScheme() != null && u.getScheme().matches("nbres(loc)?")) { //NOI18N + params.put("resource", u.getPath()); //NOI18N + } + } + ModifiersTree mt = ctx.addAnnotation(wc, modifiers, MIMERESOLVER_REGISTRATION, null, params); + wc.rewrite(modifiers, GeneratorUtilities.get(wc).importFQNs(mt)); + ctx.delete(file); + } + } + + private static abstract class AbstractMimeSpecificResolver implements Context.ModifyDeclarationTask { + + private final Context ctx; + private final String annotation; + final Registration registration; + + public AbstractMimeSpecificResolver(Context ctx, Registration registration, String annotation) { + this.ctx = ctx; + this.annotation = annotation; + this.registration = registration; + } + + @Override + public void run(WorkingCopy wc, Element declaration, ModifiersTree modifiers) throws Exception { + Map params = new HashMap(); + FileObject file = ctx.file(); + String displayName = ctx.bundlevalue(file.getAttribute("literal:displayName"), declaration); //NOI18N + + if (displayName == null) { + // checkAttributes method tries to warn user to avoid this fallback + // unaware if fix can be chained + displayName = "#TODO"; //NOI18N + } + params.put("position", file.getAttribute("position")); //NOI18N + params.put("displayName", displayName); //NOI18N + specificRun(wc, declaration, modifiers, params); + + ModifiersTree mt = ctx.addAnnotation(wc, modifiers, annotation, null, params); + wc.rewrite(modifiers, GeneratorUtilities.get(wc).importFQNs(mt)); + } + + public abstract void specificRun(WorkingCopy wc, Element declaration, ModifiersTree modifiers, Map params); + } + + private static class RegisterMIMENamespaceResolver extends AbstractMimeSpecificResolver { + + private static final String MIMERESOLVER_NAMESPACEREGISTRATION = "org.openide.filesystems.MIMEResolver.NamespaceRegistration"; //NOI18N + + public RegisterMIMENamespaceResolver(Context ctx, NamespaceRegistration nr) { + super(ctx, nr, MIMERESOLVER_NAMESPACEREGISTRATION); + } + + @Override + public void specificRun(WorkingCopy wc, Element declaration, ModifiersTree modifiers, Map params) { + params.put("mimeType", registration.mime); //NOI18N + if (!registration.getExt().isEmpty()) { + params.put("acceptedExtension", registration.getExt().toArray()); //NOI18N + } + //params.put("checkedExtension", ((NamespaceRegistration)registration).getExt()); + if (!((NamespaceRegistration) registration).getRootElement().isEmpty()) { + params.put("elementName", ((NamespaceRegistration) registration).getRootElement()); //NOI18N + } + if (!((NamespaceRegistration) registration).getElementNS().isEmpty()) { + params.put("elementNS", ((NamespaceRegistration) registration).getElementNS().toArray()); //NOI18N + } + if (!((NamespaceRegistration) registration).getPublicID().isEmpty()) { + params.put("doctypePublicId", ((NamespaceRegistration) registration).getPublicID().toArray()); //NOI18N + } + + } + } + + private static class RegisterMIMEExtensionResolver extends AbstractMimeSpecificResolver { + + private static final String MIMERESOLVER_EXTENSIONREGISTRATION = "org.openide.filesystems.MIMEResolver.ExtensionRegistration"; //NOI18N + + public RegisterMIMEExtensionResolver(Context ctx, ExtensionRegistration er) { + super(ctx, er, MIMERESOLVER_EXTENSIONREGISTRATION); + } + + @Override + public void specificRun(WorkingCopy wc, Element declaration, ModifiersTree modifiers, Map params) { + params.put("mimeType", registration.mime); //NOI18N + if (!registration.getExt().isEmpty()) { + params.put("extension", registration.getExt().toArray()); //NOI18N + } + } + } + + protected abstract class Registration { + + List ext = new ArrayList(); + String mime; + + public Registration(String mime) { + this.mime = mime; + } + + public void addExt(String mimeType) { + ext.add(mimeType); + } + + public List getExt() { + return ext; + } + } + + protected class ExtensionRegistration extends Registration { + + public ExtensionRegistration(String mime) { + super(mime); + } + } + + protected class NamespaceRegistration extends Registration { + + List elementNS = new ArrayList(); + List doctype = new ArrayList(); + String rootElement = ""; //NOI18N + + public NamespaceRegistration(String mime) { + super(mime); + } + + private void addPublicId(String publicid) { + doctype.add(publicid); + } + + public List getPublicID() { + return doctype; + } + + public void setRootElement(String rootElement) { + this.rootElement = rootElement; + } + + public String getRootElement() { + return this.rootElement; + } + + private void addElementNS(String attribute) { + elementNS.add(attribute); + } + + public List getElementNS() { + return elementNS; + } + } + + class MIMEResolverStrategyManager { + + private URL file; + protected Map extensionsRegistrations = new HashMap(); + protected Map nameSpaceRegistrations = new HashMap(); + private boolean useComplex; //private List<> ; + + MIMEResolverStrategyManager(URL mimeXmlUrl) { + file = mimeXmlUrl; + useComplex = false; + // parse file + try { + Document doc = XMLUtil.parse(new InputSource(file.toString()), false, false, null, new EntityResolver() { + + @Override + public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { + if (publicId.contains("-//NetBeans//DTD MIME Resolver")) { //NOI18N + return new InputSource(new ByteArrayInputStream(new byte[0])); + } else { + return EntityCatalog.getDefault().resolveEntity(publicId, systemId); + + } + } + }); + NodeList nl = doc.getElementsByTagName("file"); //NOI18N + for (int i = 0; + i < nl.getLength(); + i++) { + useComplex = useComplex || filterAFile(nl.item(i)); + } + } catch (SAXException ex) { + Exceptions.printStackTrace(ex); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + + private boolean filterAFile(Node nl) { + int invalidTags = 0; // according to dtd 1.1 +// + // ext is not invalid + invalidTags += ((org.w3c.dom.Element) nl).getElementsByTagName("mime").getLength(); //NOI18N + invalidTags += ((org.w3c.dom.Element) nl).getElementsByTagName("magic").getLength(); //NOI18N + invalidTags += ((org.w3c.dom.Element) nl).getElementsByTagName("fattr").getLength(); //NOI18N + invalidTags += ((org.w3c.dom.Element) nl).getElementsByTagName("pattern").getLength(); //NOI18N + invalidTags += ((org.w3c.dom.Element) nl).getElementsByTagName("name").getLength(); //NOI18N +// + // resolver is not invalid + invalidTags += ((org.w3c.dom.Element) nl).getElementsByTagName("exit").getLength(); //NOI18N + + boolean registrationForcedToXML = invalidTags > 0; + if (!registrationForcedToXML) { + NodeList resolver = ((org.w3c.dom.Element) nl).getElementsByTagName("resolver"); //NOI18N + assert (resolver.getLength() == 1); + org.w3c.dom.Element resolverElement = (org.w3c.dom.Element) resolver.item(0); + String mimeType = resolverElement.getAttribute("mime"); //NOI18N + assert (!mimeType.isEmpty()); + if (((org.w3c.dom.Element) nl).getElementsByTagName("xml-rule").getLength() > 0) { //NOI18N + registrationForcedToXML = registrationForcedToXML || addNamespaceRegistration(mimeType, nl); + } else { + addExtRegistration(mimeType, nl); + } + } + return registrationForcedToXML; + } + + private boolean addNamespaceRegistration(String mime, Node nl) { + NamespaceRegistration namespaceRegistation = nameSpaceRegistrations.get(mime); + if (namespaceRegistation == null) { + namespaceRegistation = new NamespaceRegistration(mime); + nameSpaceRegistrations.put(mime, namespaceRegistation); + } + + addExtension(namespaceRegistation, nl); + // pi not taken into account + boolean registrationForcedToXML = ((org.w3c.dom.Element) nl).getElementsByTagName("pi").getLength() > 0; //NOI18N + if (!registrationForcedToXML) { // no pi + // check for doctype + // DOCTYPE part + NodeList doctype = ((org.w3c.dom.Element) nl).getElementsByTagName("doctype"); //NOI18N + assert (doctype.getLength() <= 1); + if (doctype.getLength() > 0) { + org.w3c.dom.Element docElement = (org.w3c.dom.Element) doctype.item(0); + if (docElement.getAttribute("public-id").isEmpty()) { //NOI18N + // getall publicidtag + NodeList publictype = ((org.w3c.dom.Element) docElement).getElementsByTagName("public-id"); //NOI18N + for (int i = 0; i < publictype.getLength(); i++) { + org.w3c.dom.Element publicElement = (org.w3c.dom.Element) publictype.item(i); + if (publicElement.getAttribute("id").isEmpty()) { //NOI18N + registrationForcedToXML = true; + } else { + namespaceRegistation.addPublicId(publicElement.getAttribute("id")); //NOI18N + } + } + } else { + namespaceRegistation.addPublicId(docElement.getAttribute("public-id")); //NOI18N + } + } + + // ELEMENT part + NodeList elementList = ((org.w3c.dom.Element) nl).getElementsByTagName("element"); //NOI18N + assert (elementList.getLength() <= 1); + if (elementList.getLength() > 0) { + org.w3c.dom.Element element = (org.w3c.dom.Element) elementList.item(0); + if (element.getAttribute("name").isEmpty()) { //NOI18N + registrationForcedToXML = true; // no name force + } else { + if (namespaceRegistation.getRootElement().isEmpty()) { + namespaceRegistation.setRootElement(element.getAttribute("name")); //NOI18N + registrationForcedToXML = ((org.w3c.dom.Element) nl).getElementsByTagName("attr").getLength() > 0; // attr attribute found => cannot handle //NOI18N + + NodeList nsList = ((org.w3c.dom.Element) element).getElementsByTagName("ns"); //NOI18N + if (nsList.getLength() > 0) { + for (int i = 0; i < nsList.getLength(); i++) { + org.w3c.dom.Element nsElement = (org.w3c.dom.Element) nsList.item(i); + if (!nsElement.getAttribute("ns").isEmpty()) { //NOI18N + namespaceRegistation.addElementNS(nsElement.getAttribute("ns")); //NOI18N + } else { + registrationForcedToXML = true; + } + } + } else { + if (!element.getAttribute("ns").isEmpty()) { //NOI18N + namespaceRegistation.addElementNS(element.getAttribute("ns")); //NOI18N + } + } + + } else { + registrationForcedToXML = true; // allready an element => fail + } + } + } + + } + return registrationForcedToXML; + } + + private void addExtRegistration(String mime, Node nl) { + ExtensionRegistration extRegistration = extensionsRegistrations.get(mime); + if (extRegistration == null) { + extRegistration = new ExtensionRegistration(mime); + extensionsRegistrations.put(mime, extRegistration); + } + addExtension(extRegistration, nl); + // thats all for extension based + } + + private void addExtension(Registration registration, Node nl) { + NodeList ext = ((org.w3c.dom.Element) nl).getElementsByTagName("ext"); //NOI18N + for (int i = 0; i < ext.getLength(); i++) { + registration.addExt((((org.w3c.dom.Element) ext.item(i)).getAttribute("name"))); //NOI18N + } + } + + /** + * @return the useComplex + */ + public boolean isUseComplex() { + return useComplex; + } + + private Map checkLoaderAccessibility(Map> visibleTarget, Context ctx) { + Map tmp = new HashMap(); + boolean loaderok = true; + for (Map.Entry extregistration : extensionsRegistrations.entrySet()) { + boolean findforthis = false; + String mime = extregistration.getKey(); + for (Map.Entry> mime2 : visibleTarget.entrySet()) { + if (mime2.getValue().contains(mime)) { + tmp.put(mime2.getKey(), new RegisterMIMEExtensionResolver(ctx, extregistration.getValue())); + findforthis = true; + } + } + loaderok = loaderok && findforthis; + } + for (Map.Entry namespaceregistration : nameSpaceRegistrations.entrySet()) { + boolean findforthis = false; + String mime = namespaceregistration.getKey(); + for (Map.Entry> mime2 : visibleTarget.entrySet()) { + if (mime2.getValue().contains(mime)) { + tmp.put(mime2.getKey(), new RegisterMIMENamespaceResolver(ctx, namespaceregistration.getValue())); + findforthis = true; + } + } + loaderok = loaderok && findforthis; + } + if (!loaderok) { // one missing + tmp.clear(); + } + return tmp; + } + } +} diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/MIMEResolverRegistrationHinterTest.java b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/MIMEResolverRegistrationHinterTest.java new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/MIMEResolverRegistrationHinterTest.java @@ -0,0 +1,195 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2012 Sun Microsystems, Inc. + */ +package org.netbeans.modules.apisupport.hints; + +import java.net.URL; +import org.netbeans.junit.NbTestCase; + +/** + * + * @author skygo + */ +public class MIMEResolverRegistrationHinterTest extends NbTestCase { + + public MIMEResolverRegistrationHinterTest(String name) { + super(name); + } + + static { + System.setProperty("java.awt.headless", "true"); + } + + @Override + protected boolean runInEQ() { + return true; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + // inspired by c mimeresolver but altered for testing purpose + public void testExtBasedSimpleResolver() throws Exception { + URL f = MIMEResolverRegistrationHinterTest.class.getResource("data/textExtBasedSimpleResolver.xml"); + MIMEResolverRegistrationHinter.MIMEResolverStrategyManager instance = + new MIMEResolverRegistrationHinter().new MIMEResolverStrategyManager(f); + assertFalse("Should not use complex", instance.isUseComplex()); + assertNotNull("should be extension registraion for text/x-c", instance.extensionsRegistrations.get("text/x-c")); + assertEquals("must be 3 element for text/x-c", instance.extensionsRegistrations.get("text/x-c").getExt().size(), 3); + assertTrue("must be .c element for text/x-c", instance.extensionsRegistrations.get("text/x-c").getExt().contains("c")); + assertTrue("must be .i element for text/x-c", instance.extensionsRegistrations.get("text/x-c").getExt().contains("i")); + assertTrue("must be .m element for text/x-c", instance.extensionsRegistrations.get("text/x-c").getExt().contains("m")); + + } + + public void testExtBasedSimpleResolver2() throws Exception { + URL f = MIMEResolverRegistrationHinterTest.class.getResource("data/textExtBasedSimpleResolver2.xml"); + MIMEResolverRegistrationHinter.MIMEResolverStrategyManager instance = new MIMEResolverRegistrationHinter().new MIMEResolverStrategyManager(f); + + assertFalse("Should not use complex", instance.isUseComplex()); + + assertNotNull("should be extension registraion for text/x-c", instance.extensionsRegistrations.get("text/x-c")); + assertEquals("must be 3 element for text / x - c { } ", instance.extensionsRegistrations.get("text/x-c").getExt().size(), 9); + assertTrue("must be .c element for text/x-c", instance.extensionsRegistrations.get("text/x-c").getExt().contains("c")); + assertTrue("must be .i element for text/x-c", instance.extensionsRegistrations.get("text/x-c").getExt().contains("i")); + assertTrue("must be .m element for text/x-c", instance.extensionsRegistrations.get("text/x-c").getExt().contains("m")); + + } + + public void testExtBasedExitSimpleResolver() { + URL f = MIMEResolverRegistrationHinterTest.class.getResource("data/testExtBasedExitSimpleResolver.xml"); + MIMEResolverRegistrationHinter.MIMEResolverStrategyManager instance = new MIMEResolverRegistrationHinter().new MIMEResolverStrategyManager(f); + + assertTrue("Should use complex", instance.isUseComplex()); + } + + public void testNamespaceRegistration() { + URL f = MIMEResolverRegistrationHinterTest.class.getResource("data/testNamespaceRegistration.xml"); + MIMEResolverRegistrationHinter.MIMEResolverStrategyManager instance = new MIMEResolverRegistrationHinter().new MIMEResolverStrategyManager(f); + assertFalse("Should not use complex", instance.isUseComplex()); + assertNull("should be no extension registraion for x-struts+xml", instance.extensionsRegistrations.get("text/x-struts+xml")); + assertNotNull("should be namespace registraion for x-struts+xml", instance.nameSpaceRegistrations.get("text/x-struts+xml")); + assertTrue("must be xml in the extension", instance.nameSpaceRegistrations.get("text/x-struts+xml").getExt().contains("xml")); + assertEquals("must be 4 plucib id ", instance.nameSpaceRegistrations.get("text/x-struts+xml").getPublicID().size(), 4); //System.err.println("fddf" + instance.nameSpaceRegistrations.get("text/x-struts+xml").getPublicID()); + assertTrue("must be -//Apache Software Foundation//DTD Struts Configuration 1.3//EN in the publicid", instance.nameSpaceRegistrations.get("text/x-struts+xml").getPublicID().contains("-//Apache Software Foundation//DTD Struts Configuration 1.3//EN")); + + } + + public void testNamespaceRegistration2() { + URL f = MIMEResolverRegistrationHinterTest.class.getResource("data/testNamespaceRegistration2.xml"); + MIMEResolverRegistrationHinter.MIMEResolverStrategyManager instance = new MIMEResolverRegistrationHinter().new MIMEResolverStrategyManager(f); + + assertFalse("Should not use complex", instance.isUseComplex()); + assertNull("should be no extension registraion for x-struts+xml", instance.extensionsRegistrations.get("text/x-struts+xml")); + assertNotNull("should be namespace registraion for x-struts+xml", instance.nameSpaceRegistrations.get("text/x-struts+xml")); + assertTrue("must be xml in the extension", instance.nameSpaceRegistrations.get("text/x-struts+xml").getExt().contains("xml")); + assertEquals("must be 4 public id ", instance.nameSpaceRegistrations.get("text/x-struts+xml").getPublicID().size(), 4); + + assertTrue("must be -//Apache Software Foundation//DTD Struts Configuration 1.3//EN in the publicid", instance.nameSpaceRegistrations.get("text/x-struts+xml").getPublicID().contains("-//Apache Software Foundation//DTD Struts Configuration 1.3//EN")); + } + + public void testNamespaceRegistration3() { + URL f = MIMEResolverRegistrationHinterTest.class.getResource("data/testNamespaceRegistration3.xml"); + MIMEResolverRegistrationHinter.MIMEResolverStrategyManager instance = new MIMEResolverRegistrationHinter().new MIMEResolverStrategyManager(f); + assertTrue("Should use complex", instance.isUseComplex()); + } + + public void testNamespaceRegistration4() { + URL f = MIMEResolverRegistrationHinterTest.class.getResource("data/testNamespaceRegistration4.xml"); + MIMEResolverRegistrationHinter.MIMEResolverStrategyManager instance = new MIMEResolverRegistrationHinter().new MIMEResolverStrategyManager(f); + assertFalse("Should not use complex", instance.isUseComplex()); + assertNull("should be no extension registraion for x-struts+xml", instance.extensionsRegistrations.get("text/x-struts+xml")); + assertNotNull("should be namespace registraion for x-struts+xml", instance.nameSpaceRegistrations.get("text/x-struts+xml")); + assertTrue("must be xml in the extension", instance.nameSpaceRegistrations.get("text/x-struts+xml").getExt().contains("xml")); + assertEquals("must be r as root element", instance.nameSpaceRegistrations.get("text/x-struts+xml").getRootElement(), "r"); //System.err.println("fddf" + instance.nameSpaceRegistrations.get("text/x-struts+xml").getPublicID()); + } + + public void testNamespaceRegistrationMorethanOneElementRoot() { + URL f = MIMEResolverRegistrationHinterTest.class.getResource("data/testNamespaceRegistration5.xml"); + MIMEResolverRegistrationHinter.MIMEResolverStrategyManager instance = new MIMEResolverRegistrationHinter().new MIMEResolverStrategyManager(f); + assertTrue("Should use complex", instance.isUseComplex()); + + URL f2 = MIMEResolverRegistrationHinterTest.class.getResource("data/testNamespaceRegistration51.xml"); + MIMEResolverRegistrationHinter.MIMEResolverStrategyManager instance2 = new MIMEResolverRegistrationHinter().new MIMEResolverStrategyManager(f2); + assertTrue("Should use complex", instance2.isUseComplex()); + } + + public void testNamespaceRegistration6() { + URL f = MIMEResolverRegistrationHinterTest.class.getResource("data/testNamespaceRegistration6.xml"); + MIMEResolverRegistrationHinter.MIMEResolverStrategyManager instance = new MIMEResolverRegistrationHinter().new MIMEResolverStrategyManager(f); + assertFalse("Should not use complex", instance.isUseComplex()); + assertNull("should be no extension registraion for x-struts+xml", instance.extensionsRegistrations.get("text/x-struts+xml")); + assertNotNull("should be namespace registraion for x-struts+xml", instance.nameSpaceRegistrations.get("text/x-struts+xml")); + assertTrue("must be xml in the extension", instance.nameSpaceRegistrations.get("text/x-struts+xml").getExt().contains("xml")); + assertEquals("must be r as root element", instance.nameSpaceRegistrations.get("text/x-struts+xml").getRootElement(), "r"); + assertTrue("must be test as namespace element", instance.nameSpaceRegistrations.get("text/x-struts+xml").getElementNS().contains("test1")); + } + + public void testNamespaceRegistrationNSinXmlResolver() { + + URL f = MIMEResolverRegistrationHinterTest.class.getResource("data/testNamespaceRegistration7.xml"); + MIMEResolverRegistrationHinter.MIMEResolverStrategyManager instance = new MIMEResolverRegistrationHinter().new MIMEResolverStrategyManager(f); + assertFalse("Should not use complex", instance.isUseComplex()); + assertNull("should be no extension registraion for x-struts+xml", instance.extensionsRegistrations.get("text/x-struts+xml")); + assertNotNull("should be namespace registraion for x-struts+xml", instance.nameSpaceRegistrations.get("text/x-struts+xml")); + assertTrue("must be xml in the extension", instance.nameSpaceRegistrations.get("text/x-struts+xml").getExt().contains("xml")); + assertEquals("must be r as root element", instance.nameSpaceRegistrations.get("text/x-struts+xml").getRootElement(), + "r"); + assertFalse("must not be test as namespace element", instance.nameSpaceRegistrations.get("text/x-struts+xml").getElementNS().contains("test1")); + + assertTrue("must be test2 as namespace element", instance.nameSpaceRegistrations.get("text/x-struts+xml").getElementNS().contains("test2")); + assertTrue("must be test3 as namespace element", instance.nameSpaceRegistrations.get("text/x-struts+xml").getElementNS().contains("test3")); + } + + public void testNamespaceRegistrationNotSupportedAttr() { + URL f = MIMEResolverRegistrationHinterTest.class.getResource("data/testNamespaceRegistration8.xml"); + MIMEResolverRegistrationHinter.MIMEResolverStrategyManager instance = new MIMEResolverRegistrationHinter().new MIMEResolverStrategyManager(f); + assertTrue("Should use complex", instance.isUseComplex()); + } + + public void testNamespaceRegistrationJ2EE() { + URL f = MIMEResolverRegistrationHinterTest.class.getResource("data/testNamespaceRegistrationJ2EE.xml"); + MIMEResolverRegistrationHinter.MIMEResolverStrategyManager instance = new MIMEResolverRegistrationHinter().new MIMEResolverStrategyManager(f); + assertFalse("Should not use complex", instance.isUseComplex()); + } +} diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testExtBasedExitSimpleResolver.xml b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testExtBasedExitSimpleResolver.xml new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testExtBasedExitSimpleResolver.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration.xml b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration.xml new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration2.xml b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration2.xml new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration2.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration3.xml b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration3.xml new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration3.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration4.xml b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration4.xml new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration5.xml b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration5.xml new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration5.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration51.xml b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration51.xml new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration51.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration6.xml b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration6.xml new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration6.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration7.xml b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration7.xml new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration7.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration8.xml b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration8.xml new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistration8.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistrationJ2EE.xml b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistrationJ2EE.xml new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/testNamespaceRegistrationJ2EE.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/textExtBasedSimpleResolver.xml b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/textExtBasedSimpleResolver.xml new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/textExtBasedSimpleResolver.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/textExtBasedSimpleResolver2.xml b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/textExtBasedSimpleResolver2.xml new file mode 100644 --- /dev/null +++ b/apisupport.refactoring/test/unit/src/org/netbeans/modules/apisupport/hints/data/textExtBasedSimpleResolver2.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file