Cannot show description or depends in UpdatePlugins.xml

Dear IDEA support,

I need create a custom repository, and I created a updatePlugins.xml. I can get the available list of my plugins, however I'm constantly facing below issues:

1) How could I show description, looks like the plugin manager won't parse description from plugin.xml,
I searched and found http://youtrack.jetbrains.com/issue/IDEA-88075, it is said I should subtag description in updatePlugins.xml

Tried with this solution however failed with "Connection failed: null", Please see attached for details.
<plugins>
    <plugin id="Test" url="http://localhost/intellij/Test/Test-2.0.jar" version="2.0">
     <description>Description for test plugin</description>
    </plugin>
</plugins>

2) How could I manage the dependencies of plugins, say, if I have a plugin UI, and another plugin Core, UI depends on Core, when user installs UI, we wish Core will be automatically picked up.
Should I declare the dependencies with "depends" in updatePlugins.xml?
I checked the code UpdateChecker, seems it is expecting child tag "depends", however I also get above exception.

And where can I get the latest DTD for updatePlugins.xml? seems the wiki is out-of-date.
http://www.jetbrains.com/idea/webhelp/adding-plugins-to-enterprise-repositories.html



Attachment(s):
e1.png
4 comments

Hi,

you may put the same file as one our repository generates (The sample should be located system/plugins/available.xml). Subtag description should work, please attach idea.log file. Depends won't work though.

0

Hi Anna,

Thanks for your quick response.
I tried replacing my updataPlugins.xml with the content like available.xml, the description can be shown and depends also work for me.
However when I try to install, I get the HTTP error as attached. Shutdown the ide and checked the error log /system/log/idea.log, there is no valued information.

Looks like I'm in the wrong direction, for below configuration,  the url actually serves as a plugin home page and will be shown in the dialog.
What I expect is a download url, I have tried setting the url with http or file:// absolute and file://relative and no vail.

From the code, intellij will download file from offical site by appending "action=download&id=", and thus it won't require the url.

As I'm using a custom repository, What should I do to make intellij aware of my plugin jars on server? Any conventions that intellij will follow to look for files on the same server with updatePlugins.xml?
or additional configurations to make intellij turn for my server?

<?xml version="1.0" encoding="UTF-8"?>
<plugin-repository>
    <ff>"Code Editing"</ff>
    <category name="Code Editing">
        <idea-plugin downloads='1875' size='70252' date='1254771039000' url='http://localhost/intellij/Test/Test-2.0.jar'>
            <name>Test</name>
            <id>Test</id>
            <description><![CDATA[served as Test]]></description>
            <version>2.0</version>
            <vendor email='' url=''>ebay</vendor>
            <idea-version min="n/a" max="n/a" since-build='40.3000'/>
            <change-notes><![CDATA[Fixed some bugs, added parameter initialization]]></change-notes>
            <rating>3.3</rating>
            <depends>com.intellij.modules.lang</depends>
        </idea-plugin>


    </category>
</plugin-repository>

Thanks,
Eric



Attachment(s):
error2.png
0

I'm using IDEA 12.1.4

updatePlugins.xml support 2 styles,  it first parse updatePlugins.xml as <plugin-repository><idea-plugin/> </plugin-repository> style, then parse as  <plugins></plugin> </plugins>.
Basically I think it is a bug, from the code, description and depends should be supported for updatePlugins.xml with <plugins></plugin> </plugins> style, however always end with a NullPointer.

I debugged the code and found the root cause:

UpdateChecker:
  inputStream = loadVersionInfo(host);
    if (inputStream == null) return false;
    final List<IdeaPluginDescriptor> descriptors = RepositoryHelper.loadPluginsFromDescription(inputStream, indicator);//parse as  <plugin-repository><idea-plugin/> </plugin-repository>
    for (IdeaPluginDescriptor descriptor : descriptors) {
      ((PluginNode)descriptor).setRepositoryName(host);
      downloaded.add(PluginDownloader.createDownloader(descriptor));
    }

    boolean success = true;
    for (Object plugin : document.getRootElement().getChildren("plugin")) {//parse as  <plugins></plugin> </plugins>
      final Element pluginElement = (Element)plugin;
      final String pluginId = pluginElement.getAttributeValue("id");
      final String pluginUrl = pluginElement.getAttributeValue("url");
      final String pluginVersion = pluginElement.getAttributeValue("version");
      final Element descriptionElement = pluginElement.getChild("description");
      final String description;
      if (descriptionElement != null) {
        description = descriptionElement.getText();
      } else {
        description = null;
      }
      
      final List<PluginId> dependsPlugins = new ArrayList<PluginId>();
      final List depends = pluginElement.getChildren("depends");
      for (Object depend : depends) {
        dependsPlugins.add(PluginId.getId(((Element)depend).getText()));
      }

      if (pluginId == null) {
        LOG.info("plugin id should not be null");
        success = false;
        continue;
      }



The RepositoryContentHandler is for parsing <plugin-repository><idea-plugin>, and when it comes to <description> tag embedded as <plugins><plugin><description/></plugin></plugins>, it tries to parse, but result with a NullPointer cause currentPlugin is Null.
This is why the <plugin><description/></plugin> or <plugin><depends/></plugin> not worked as expected.

RepositoryContentHandler:

else if (qName.equals(IDEA_PLUGIN)) {
      String categoryName = constructCategoryTree();
      currentPlugin = new PluginNode();// the currentPlugin will be initialized unless the outter tag is <idea-plugin>
      currentPlugin.setCategory(categoryName);
      currentPlugin.setDownloads(atts.getValue(DOWNLOADS));
      currentPlugin.setSize(atts.getValue(SIZE));
      currentPlugin.setUrl(atts.getValue(URL));
      currentPlugin.setDate(atts.getValue(DATE));

      plugins.add(currentPlugin);
    }

public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
    if (qName.equals(ID)) {
      currentPlugin.setId(currentValue);
    }
    else if (qName.equals(NAME)) {
      currentPlugin.setName(currentValue);
    }
    else if (qName.equals(DESCRIPTION)) {
      currentPlugin.setDescription(currentValue);//currentPlugin is null and throw below exception
    }

java.lang.NullPointerException
    at com.intellij.ide.plugins.RepositoryContentHandler.endElement(RepositoryContentHandler.java:99)
    at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
    at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
    at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at org.apache.xerces.jaxp.SAXParserImpl.parse(Unknown Source)
    at javax.xml.parsers.SAXParser.parse(Unknown Source)
    at com.intellij.ide.plugins.RepositoryHelper.readPluginsStream(RepositoryHelper.java:149)
    at com.intellij.ide.plugins.RepositoryHelper.loadPluginsFromDescription(RepositoryHelper.java:161)
    at com.intellij.openapi.updateSettings.impl.UpdateChecker.checkPluginsHost(UpdateChecker.java:309)
    at com.intellij.openapi.updateSettings.impl.UpdateChecker.checkPluginsHost(UpdateChecker.java:287)
    at com.intellij.ide.plugins.PluginHostsConfigurable$HostMessages$InputHostDialog$1$1.run(PluginHostsConfigurable.java:189)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl$5.run(ProgressManagerImpl.java:291)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl$TaskRunnable.run(ProgressManagerImpl.java:495)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl$6.run(ProgressManagerImpl.java:304)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl$2.run(ProgressManagerImpl.java:185)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:226)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl.runProcess(ProgressManagerImpl.java:175)
    at com.intellij.openapi.application.impl.ApplicationImpl$10$1.run(ApplicationImpl.java:681)
    at com.intellij.openapi.application.impl.ApplicationImpl$8.run(ApplicationImpl.java:454)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:452)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:314)
    at java.util.concurrent.FutureTask.run(FutureTask.java:149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:896)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:735)
    at com.intellij.openapi.application.impl.ApplicationImpl$1$1.run(ApplicationImpl.java:152)

Please let me know if there is a workaround not only support description and depends, but also support downloading plugin jar files on the same server with updatePlugins.xml.

0

Exactly, IDEA parses updatePlugins.xml first as a common-repository content and then tries the simple format. In simple format dependencies won't work as they are not expected to work there. I see the issue with download url here. So please vote/watch the issue http://youtrack.jetbrains.com/issue/IDEA-112778
Thanks

0

Please sign in to leave a comment.