From 2fa869f812dd92163632b3bbb982db0e482c709a Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 23 Jul 2012 14:43:33 +0400 Subject: [PATCH] IDEA-27620 XML Catalog support: initial --- ...ghtPlatformCodeInsightFixtureTestCase.java | 24 ++++-- .../javaee/ExternalResourceConfigurable.java | 12 ++- .../javaee/ExternalResourceManagerEx.java | 3 + .../javaee/ExternalResourceManagerImpl.java | 37 +++++++- .../javaee/XMLCatalogConfigurable.form | 32 +++++++ .../javaee/XMLCatalogConfigurable.java | 69 +++++++++++++++ .../intellij/javaee/XMLCatalogManager.java | 85 +++++++++++++++++++ .../intellij/xml/XMLCatalogManagerTest.java | 69 +++++++++++++++ xml/tests/testData/catalog/catalog.properties | 4 + xml/tests/testData/catalog/catalog.xml | 8 ++ 10 files changed, 331 insertions(+), 12 deletions(-) create mode 100644 xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.form create mode 100644 xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java create mode 100644 xml/impl/src/com/intellij/javaee/XMLCatalogManager.java create mode 100644 xml/tests/src/com/intellij/xml/XMLCatalogManagerTest.java create mode 100644 xml/tests/testData/catalog/catalog.properties create mode 100644 xml/tests/testData/catalog/catalog.xml diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/LightPlatformCodeInsightFixtureTestCase.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/LightPlatformCodeInsightFixtureTestCase.java index 851b9e11a965..07d31747eadb 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/LightPlatformCodeInsightFixtureTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/LightPlatformCodeInsightFixtureTestCase.java @@ -26,6 +26,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; import com.intellij.psi.PsiManager; import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl; import org.jetbrains.annotations.NonNls; @@ -77,15 +78,20 @@ public abstract class LightPlatformCodeInsightFixtureTestCase extends UsefulTest return null; } - /** - * Return absolute path to the test data. - * - * @return absolute path to the test data. - */ - @NonNls - protected String getTestDataPath() { - return PathManager.getHomePath().replace(File.separatorChar, '/') + getBasePath(); - } + /** + * Return absolute path to the test data. Not intended to be overridden. + * + * @return absolute path to the test data. + */ + @NonNls + protected String getTestDataPath() { + String path = isCommunity() ? PlatformTestUtil.getCommunityPath() : PathManager.getHomePath(); + return path.replace(File.separatorChar, '/') + getBasePath(); + } + + protected boolean isCommunity() { + return false; + } @Override protected void runTest() throws Throwable { diff --git a/xml/impl/src/com/intellij/javaee/ExternalResourceConfigurable.java b/xml/impl/src/com/intellij/javaee/ExternalResourceConfigurable.java index c0009cd8fd13..8c1e5d7e2022 100644 --- a/xml/impl/src/com/intellij/javaee/ExternalResourceConfigurable.java +++ b/xml/impl/src/com/intellij/javaee/ExternalResourceConfigurable.java @@ -44,7 +44,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -public class ExternalResourceConfigurable extends BaseConfigurable implements SearchableConfigurable, OptionalConfigurable, Configurable.NoScroll { +public class ExternalResourceConfigurable extends BaseConfigurable + implements SearchableConfigurable, OptionalConfigurable, Configurable.NoScroll, Configurable.Composite { private JPanel myPanel; private List myPairs; private List myIgnoredUrls; @@ -54,6 +55,7 @@ public class ExternalResourceConfigurable extends BaseConfigurable implements Se private HtmlLanguageLevelForm myHtmlLanguageLevelForm; @Nullable private final Project myProject; private final List myNewPairs; + private Configurable[] myConfigurables; public ExternalResourceConfigurable(@Nullable Project project) { this(project, Collections.emptyList()); @@ -282,6 +284,14 @@ public class ExternalResourceConfigurable extends BaseConfigurable implements Se return dialog.getPair().myName; } + @Override + public Configurable[] getConfigurables() { + if (myConfigurables == null) { + myConfigurables = new Configurable[]{new XMLCatalogConfigurable()}; + } + return myConfigurables; + } + private static class PathRenderer extends DefaultTableCellRenderer { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { final Component rendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); diff --git a/xml/impl/src/com/intellij/javaee/ExternalResourceManagerEx.java b/xml/impl/src/com/intellij/javaee/ExternalResourceManagerEx.java index f22e181b0b05..d327ac4beb7c 100644 --- a/xml/impl/src/com/intellij/javaee/ExternalResourceManagerEx.java +++ b/xml/impl/src/com/intellij/javaee/ExternalResourceManagerEx.java @@ -59,5 +59,8 @@ public abstract class ExternalResourceManagerEx extends ExternalResourceManager public abstract void setDefaultHtmlDoctype(@NotNull String defaultHtmlDoctype, @NotNull Project project); + public abstract String getCatalogPropertiesFile(); + public abstract void setCatalogPropertiesFile(String filePath); + public abstract long getModificationCount(@NotNull Project project); } diff --git a/xml/impl/src/com/intellij/javaee/ExternalResourceManagerImpl.java b/xml/impl/src/com/intellij/javaee/ExternalResourceManagerImpl.java index 8e102fef1123..0441f83b15aa 100644 --- a/xml/impl/src/com/intellij/javaee/ExternalResourceManagerImpl.java +++ b/xml/impl/src/com/intellij/javaee/ExternalResourceManagerImpl.java @@ -35,6 +35,7 @@ import com.intellij.util.containers.HashMap; import com.intellij.xml.Html5SchemaProvider; import com.intellij.xml.XmlSchemaProvider; import com.intellij.xml.util.XmlUtil; +import com.sun.org.apache.xml.internal.resolver.CatalogManager; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -57,6 +58,7 @@ public class ExternalResourceManagerImpl extends ExternalResourceManagerEx imple @NonNls public static final String J2EE_1_2 = "http://java.sun.com/j2ee/dtds/"; @NonNls public static final String J2EE_NS = "http://java.sun.com/xml/ns/j2ee/"; @NonNls public static final String JAVAEE_NS = "http://java.sun.com/xml/ns/javaee/"; + private static final String CATALOG_PROPERTIES_ELEMENT = "CATALOG_PROPERTIES"; private final Map> myResources = new HashMap>(); @@ -75,6 +77,10 @@ public class ExternalResourceManagerImpl extends ExternalResourceManagerEx imple private String myDefaultHtmlDoctype = Html5SchemaProvider.HTML5_SCHEMA_LOCATION; + private String myCatalogPropertiesFile; + private CatalogManager myCatalogManager; + + protected Map> computeStdResources() { ResourceRegistrarImpl registrar = new ResourceRegistrarImpl(); for (StandardResourceProvider provider : Extensions.getExtensions(StandardResourceProvider.EP_NAME)) { @@ -140,6 +146,7 @@ public class ExternalResourceManagerImpl extends ExternalResourceManagerEx imple if (result == null) { result = getStdResource(url, version); } +// getCatalogManager().getCatalog().resolveURI() if (result == null) { result = url; } @@ -349,9 +356,13 @@ public class ExternalResourceManagerImpl extends ExternalResourceManagerEx imple } Element child = element.getChild(HTML_DEFAULT_DOCTYPE_ELEMENT); - if (child != null && child.getText() != null) { + if (child != null) { myDefaultHtmlDoctype = child.getText(); } + Element catalogElement = element.getChild(CATALOG_PROPERTIES_ELEMENT); + if (catalogElement != null) { + myCatalogPropertiesFile = catalogElement.getTextTrim(); + } } public void writeExternal(Element element) throws WriteExternalException { @@ -380,7 +391,11 @@ public class ExternalResourceManagerImpl extends ExternalResourceManagerEx imple e.setText(myDefaultHtmlDoctype); element.addContent(e); } - + if (myCatalogPropertiesFile != null) { + Element properties = new Element(CATALOG_PROPERTIES_ELEMENT); + properties.setText(myCatalogPropertiesFile); + element.addContent(properties); + } final ReplacePathToMacroMap macroReplacements = new ReplacePathToMacroMap(); PathMacrosImpl.getInstanceEx().addMacroReplacements(macroReplacements); macroReplacements.substitute(element, SystemInfo.isFileSystemCaseSensitive); @@ -423,6 +438,24 @@ public class ExternalResourceManagerImpl extends ExternalResourceManagerEx imple getProjectResources(project).setDefaultHtmlDoctype(defaultHtmlDoctype); } + @Override + public String getCatalogPropertiesFile() { + return myCatalogPropertiesFile; + } + + @Override + public void setCatalogPropertiesFile(String filePath) { + myCatalogManager = null; + myCatalogPropertiesFile = filePath; + } + + private CatalogManager getCatalogManager() { + if (myCatalogManager == null) { + myCatalogManager = new CatalogManager(myCatalogPropertiesFile); + } + return myCatalogManager; + } + private void setDefaultHtmlDoctype(String defaultHtmlDoctype) { myModificationCount++; myDefaultHtmlDoctype = defaultHtmlDoctype; diff --git a/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.form b/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.form new file mode 100644 index 000000000000..660dca5dbcf7 --- /dev/null +++ b/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.form @@ -0,0 +1,32 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java b/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java new file mode 100644 index 000000000000..5f39dbd840f4 --- /dev/null +++ b/xml/impl/src/com/intellij/javaee/XMLCatalogConfigurable.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.javaee; + +import com.intellij.openapi.options.BaseConfigurable; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import org.jetbrains.annotations.Nls; + +import javax.swing.*; + +/** + * @author Dmitry Avdeev + * Date: 7/20/12 + */ +public class XMLCatalogConfigurable extends BaseConfigurable { + + private TextFieldWithBrowseButton myPropertyFile; + private JPanel myPanel; + + @Nls + @Override + public String getDisplayName() { + return "XML Catalog"; + } + + @Override + public String getHelpTopic() { + return null; + } + + @Override + public JComponent createComponent() { + return myPanel; + } + + @Override + public JComponent getPreferredFocusedComponent() { + return myPropertyFile.getTextField(); + } + + @Override + public void apply() throws ConfigurationException { + ExternalResourceManagerEx.getInstanceEx().setCatalogPropertiesFile(myPropertyFile.getText()); + } + + @Override + public void reset() { + myPropertyFile.setText(ExternalResourceManagerEx.getInstanceEx().getCatalogPropertiesFile()); + } + + @Override + public void disposeUIResources() { + + } +} diff --git a/xml/impl/src/com/intellij/javaee/XMLCatalogManager.java b/xml/impl/src/com/intellij/javaee/XMLCatalogManager.java new file mode 100644 index 000000000000..180126bcd7c8 --- /dev/null +++ b/xml/impl/src/com/intellij/javaee/XMLCatalogManager.java @@ -0,0 +1,85 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.javaee; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.io.FileUtil; +import com.sun.org.apache.xml.internal.resolver.CatalogManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; + +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.lang.reflect.Field; +import java.util.PropertyResourceBundle; + +/** + * @author Dmitry Avdeev + * Date: 7/20/12 + */ +public class XMLCatalogManager { + + private final static Logger LOG = Logger.getInstance(XMLCatalogManager.class); + + private static Field ourResources; + private static Field ourPropertyFileUri; + + static { + try { + ourResources = CatalogManager.class.getDeclaredField("resources"); + ourResources.setAccessible(true); + ourPropertyFileUri = CatalogManager.class.getDeclaredField("propertyFileURI"); + ourPropertyFileUri.setAccessible(true); + } + catch (NoSuchFieldException e) { + LOG.error(e); + } + } + + private final CatalogManager myManager = new CatalogManager(); + + public XMLCatalogManager(@NotNull String propertiesFilePath) throws IOException { + + File file = new File(propertiesFilePath); + String s = FileUtil.loadFile(file); + PropertyResourceBundle bundle = new PropertyResourceBundle(new StringReader(s)); + try { + ourResources.set(myManager, bundle); + ourPropertyFileUri.set(myManager, file.toURI().toURL()); + } + catch (IllegalAccessException e) { + LOG.error(e); + } + } + + @Nullable + public String resolve(String uri) { + try { + return myManager.getCatalog().resolvePublic(uri, null); + } + catch (IOException e) { + LOG.warn(e); + return null; + } + } + + @TestOnly + public CatalogManager getManager() { + return myManager; + } +} diff --git a/xml/tests/src/com/intellij/xml/XMLCatalogManagerTest.java b/xml/tests/src/com/intellij/xml/XMLCatalogManagerTest.java new file mode 100644 index 000000000000..39987f0119e5 --- /dev/null +++ b/xml/tests/src/com/intellij/xml/XMLCatalogManagerTest.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.xml; + +import com.intellij.javaee.XMLCatalogManager; +import com.intellij.testFramework.IdeaTestCase; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; +import com.sun.org.apache.xml.internal.resolver.CatalogManager; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.util.Vector; + +/** + * @author Dmitry Avdeev + * Date: 7/20/12 + */ +@SuppressWarnings("UseOfObsoleteCollectionType") +public class XMLCatalogManagerTest extends LightPlatformCodeInsightFixtureTestCase { + + public void testCatalogManager() throws Exception { + XMLCatalogManager manager = getManager(); + CatalogManager catalogManager = manager.getManager(); + Vector files = catalogManager.getCatalogFiles(); + assertEquals(1, files.size()); + String filePath = (String)files.get(0); + assertTrue(filePath, filePath.endsWith("catalog.xml")); + assertTrue(filePath, new File(new URI(filePath)).exists()); + } + + public void testResolve() throws Exception { + String resolve = getManager().resolve("-//W3C//DTD XHTML 1.0 Strict//EN"); + assertNotNull(resolve); + assertTrue(resolve, resolve.endsWith("/catalog/xhtml1-strict.dtd")); + } + + private XMLCatalogManager getManager() throws IOException { + return new XMLCatalogManager(getTestDataPath() + "catalog.properties"); + } + + @Override + protected String getBasePath() { + return "/xml/tests/testData/catalog/"; + } + + @Override + protected boolean isCommunity() { + return true; + } + + @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors") + public XMLCatalogManagerTest() { + IdeaTestCase.initPlatformPrefix(); + } +} diff --git a/xml/tests/testData/catalog/catalog.properties b/xml/tests/testData/catalog/catalog.properties new file mode 100644 index 000000000000..a6cb7b857b3d --- /dev/null +++ b/xml/tests/testData/catalog/catalog.properties @@ -0,0 +1,4 @@ +# Catalogs are relative to this properties file +relative-catalogs=false +# Catalog list +catalogs=catalog.xml \ No newline at end of file diff --git a/xml/tests/testData/catalog/catalog.xml b/xml/tests/testData/catalog/catalog.xml new file mode 100644 index 000000000000..acb48871b955 --- /dev/null +++ b/xml/tests/testData/catalog/catalog.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file