IDEA-27620 XML Catalog support: initial

This commit is contained in:
Dmitry Avdeev
2012-07-23 15:38:29 +04:00
parent 89c7aa083d
commit 2fa869f812
10 changed files with 331 additions and 12 deletions
@@ -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 {
@@ -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<NameLocationPair> myPairs;
private List<String> myIgnoredUrls;
@@ -54,6 +55,7 @@ public class ExternalResourceConfigurable extends BaseConfigurable implements Se
private HtmlLanguageLevelForm myHtmlLanguageLevelForm;
@Nullable private final Project myProject;
private final List<NameLocationPair> myNewPairs;
private Configurable[] myConfigurables;
public ExternalResourceConfigurable(@Nullable Project project) {
this(project, Collections.<NameLocationPair>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);
@@ -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);
}
@@ -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<String, Map<String, String>> myResources = new HashMap<String, Map<String, String>>();
@@ -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<String, Map<String, Resource>> 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;
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.javaee.XMLCatalogConfigurable">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="46"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="5b144" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Catalog property file:"/>
</properties>
</component>
<component id="b541d" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myPropertyFile">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<vspacer id="fd213">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
</form>
@@ -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() {
}
}
@@ -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;
}
}
@@ -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();
}
}
@@ -0,0 +1,4 @@
# Catalogs are relative to this properties file
relative-catalogs=false
# Catalog list
catalogs=catalog.xml
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog
xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<public publicId="-//W3C//DTD XHTML 1.0 Strict//EN"
uri="xhtml1-strict.dtd"/>
</catalog>