Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.intellij.javaee.ExternalResourceManagerExImpl Maven / Gradle / Ivy
Go to download
A packaging of the IntelliJ Community Edition xml-psi-impl library.
This is release number 1 of trunk branch 142.
/*
* Copyright 2000-2015 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.application.options.PathMacrosImpl;
import com.intellij.application.options.ReplacePathToMacroMap;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.xml.Html5SchemaProvider;
import com.intellij.xml.XmlSchemaProvider;
import com.intellij.xml.index.XmlNamespaceIndex;
import com.intellij.xml.util.XmlUtil;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.io.File;
import java.net.URL;
import java.util.*;
@State(
name = "ExternalResourceManagerImpl",
storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml")}
)
public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx implements PersistentStateComponent {
static final Logger LOG = Logger.getInstance(ExternalResourceManagerExImpl.class);
@NonNls public static final String J2EE_1_3 = "http://java.sun.com/dtd/";
@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 static final String XSD_1_1 = new Resource("/standardSchemas/XMLSchema-1_1/XMLSchema.xsd", ExternalResourceManagerExImpl.class, null).getResourceUrl();
private final Map> myResources = new THashMap>();
private final Set myResourceLocations = new THashSet();
private final Set myIgnoredResources = new TreeSet();
private final Set myStandardIgnoredResources = new TreeSet();
private final NotNullLazyValue>> myStandardResources = new AtomicNotNullLazyValue>>() {
@NotNull
@Override
protected Map> compute() {
return computeStdResources();
}
};
private final CachedValueProvider> myUrlByNamespaceProvider = new CachedValueProvider>() {
@Nullable
@Override
public CachedValueProvider.Result> compute() {
MultiMap result = new MultiMap();
Collection> values = myStandardResources.getValue().values();
for (Map map : values) {
for (Map.Entry entry : map.entrySet()) {
String url = entry.getValue().getResourceUrl();
if (url != null) {
VirtualFile file = VfsUtilCore.findRelativeFile(url, null);
if (file != null) {
String namespace = XmlNamespaceIndex.computeNamespace(file);
if (namespace != null) {
result.putValue(namespace, entry.getKey());
}
}
}
}
}
return CachedValueProvider.Result.create(result, ExternalResourceManagerExImpl.this);
}
};
private String myDefaultHtmlDoctype = HTML5_DOCTYPE_ELEMENT;
private XMLSchemaVersion myXMLSchemaVersion = XMLSchemaVersion.XMLSchema_1_0;
private String myCatalogPropertiesFile;
private XMLCatalogManager myCatalogManager;
private static final String HTML5_DOCTYPE_ELEMENT = "HTML5";
protected Map> computeStdResources() {
ResourceRegistrarImpl registrar = new ResourceRegistrarImpl();
for (StandardResourceProvider provider : StandardResourceProvider.EP_NAME.getExtensions()) {
provider.registerResources(registrar);
}
for (StandardResourceEP extension : StandardResourceEP.EP_NAME.getExtensions()) {
registrar.addStdResource(extension.url, extension.version, extension.resourcePath, null, extension.getLoaderForClass());
}
myStandardIgnoredResources.addAll(registrar.getIgnored());
return registrar.getResources();
}
private final List myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
@NonNls private static final String RESOURCE_ELEMENT = "resource";
@NonNls private static final String URL_ATTR = "url";
@NonNls private static final String LOCATION_ATTR = "location";
@NonNls private static final String IGNORED_RESOURCE_ELEMENT = "ignored-resource";
@NonNls private static final String HTML_DEFAULT_DOCTYPE_ELEMENT = "default-html-doctype";
@NonNls private static final String XML_SCHEMA_VERSION = "xml-schema-version";
private static final String DEFAULT_VERSION = "";
@Override
public boolean isStandardResource(VirtualFile file) {
VirtualFile parent = file.getParent();
return parent != null && parent.getName().equals("standardSchemas");
}
@Override
public boolean isUserResource(VirtualFile file) {
return myResourceLocations.contains(file.getUrl());
}
@Nullable
static Map getMap(@NotNull Map> resources, @Nullable String version, boolean create) {
version = StringUtil.notNullize(version, DEFAULT_VERSION);
Map map = resources.get(version);
if (map == null) {
if (create) {
map = new THashMap();
resources.put(version, map);
}
else if (!version.equals(DEFAULT_VERSION)) {
map = resources.get(DEFAULT_VERSION);
}
}
return map;
}
@Override
public String getResourceLocation(@NotNull String url) {
return getResourceLocation(url, DEFAULT_VERSION);
}
@Override
public String getResourceLocation(@NotNull @NonNls String url, @Nullable String version) {
String result = getUserResource(url, StringUtil.notNullize(version, DEFAULT_VERSION));
if (result == null) {
XMLCatalogManager manager = getCatalogManager();
if (manager != null) {
result = manager.resolve(url);
}
if (result == null) {
result = getStdResource(url, version);
if (result == null) {
return url;
}
}
}
return result;
}
@Override
@Nullable
public String getUserResource(Project project, String url, String version) {
String resource = getProjectResources(project).getUserResource(url, version);
return resource == null ? getUserResource(url, version) : resource;
}
@Override
@Nullable
public String getStdResource(@NotNull String url, @Nullable String version) {
Map map = getMap(myStandardResources.getValue(), version, false);
if (map != null) {
Resource resource = map.get(url);
return resource == null ? null : resource.getResourceUrl();
}
else {
return null;
}
}
@Nullable
private String getUserResource(@NotNull String url, @Nullable String version) {
Map map = getMap(myResources, version, false);
return map != null ? map.get(url) : null;
}
@Override
public String getResourceLocation(@NotNull @NonNls String url, @NotNull Project project) {
return getResourceLocation(url, null, project);
}
private String getResourceLocation(@NonNls String url, String version, @NotNull Project project) {
ExternalResourceManagerExImpl projectResources = getProjectResources(project);
String location = projectResources.getResourceLocation(url, version);
if (location == null || location.equals(url)) {
if (projectResources.myXMLSchemaVersion == XMLSchemaVersion.XMLSchema_1_1) {
if (XmlUtil.XML_SCHEMA_URI.equals(url)) return XSD_1_1;
if ((XmlUtil.XML_SCHEMA_URI + ".xsd").equals(url)) return XSD_1_1;
}
return getResourceLocation(url, version);
}
else {
return location;
}
}
@Override
@Nullable
public PsiFile getResourceLocation(@NotNull @NonNls final String url, @NotNull final PsiFile baseFile, final String version) {
final XmlFile schema = XmlSchemaProvider.findSchema(url, baseFile);
if (schema != null) {
return schema;
}
final String location = getResourceLocation(url, version, baseFile.getProject());
return XmlUtil.findXmlFile(baseFile, location);
}
@Override
public String[] getResourceUrls(FileType fileType, boolean includeStandard) {
return getResourceUrls(fileType, DEFAULT_VERSION, includeStandard);
}
@Override
public String[] getResourceUrls(@Nullable FileType fileType, @Nullable @NonNls String version, boolean includeStandard) {
List result = new LinkedList();
addResourcesFromMap(result, version, myResources);
if (includeStandard) {
addResourcesFromMap(result, version, myStandardResources.getValue());
}
return ArrayUtil.toStringArray(result);
}
private static void addResourcesFromMap(@NotNull List result, @Nullable String version, @NotNull Map> resourcesMap) {
Map resources = getMap(resourcesMap, version, false);
if (resources != null) {
result.addAll(resources.keySet());
}
}
@TestOnly
public static void addTestResource(final String url, final String location, Disposable parentDisposable) {
final ExternalResourceManagerExImpl instance = (ExternalResourceManagerExImpl)getInstance();
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
instance.addResource(url, location);
}
});
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
instance.removeResource(url);
}
});
}
});
}
@Override
public void addResource(@NotNull String url, String location) {
addResource(url, DEFAULT_VERSION, location);
}
@Override
public void addResource(@NotNull @NonNls String url, @NonNls String version, @NonNls String location) {
ApplicationManager.getApplication().assertWriteAccessAllowed();
addSilently(url, version, location);
fireExternalResourceChanged();
}
private void addSilently(@NotNull String url, @Nullable String version, String location) {
Map map = getMap(myResources, version, true);
assert map != null;
map.put(url, location);
myResourceLocations.add(location);
incModificationCount();
}
@Override
public void removeResource(@NotNull String url) {
removeResource(url, DEFAULT_VERSION);
}
@Override
public void removeResource(@NotNull String url, @Nullable String version) {
ApplicationManager.getApplication().assertWriteAccessAllowed();
Map map = getMap(myResources, version, false);
if (map != null) {
String location = map.remove(url);
if (location != null) {
myResourceLocations.remove(location);
}
incModificationCount();
fireExternalResourceChanged();
}
}
@Override
public void removeResource(String url, @NotNull Project project) {
getProjectResources(project).removeResource(url);
}
@Override
public void addResource(@NonNls String url, @NonNls String location, @NotNull Project project) {
getProjectResources(project).addResource(url, location);
}
@Override
public String[] getAvailableUrls() {
Set urls = new THashSet();
for (Map map : myResources.values()) {
urls.addAll(map.keySet());
}
return ArrayUtil.toStringArray(urls);
}
@Override
public String[] getAvailableUrls(Project project) {
return getProjectResources(project).getAvailableUrls();
}
@Override
public void clearAllResources() {
myResources.clear();
myIgnoredResources.clear();
}
@Override
public void clearAllResources(Project project) {
ApplicationManager.getApplication().assertWriteAccessAllowed();
clearAllResources();
getProjectResources(project).clearAllResources();
incModificationCount();
fireExternalResourceChanged();
}
@Override
public void addIgnoredResource(@NotNull String url) {
ApplicationManager.getApplication().assertWriteAccessAllowed();
if (addIgnoredSilently(url)) {
fireExternalResourceChanged();
}
}
private boolean addIgnoredSilently(@NotNull String url) {
if (myStandardIgnoredResources.contains(url)) {
return false;
}
if (myIgnoredResources.add(url)) {
incModificationCount();
return true;
}
else {
return false;
}
}
@Override
public void removeIgnoredResource(@NotNull String url) {
ApplicationManager.getApplication().assertWriteAccessAllowed();
if (myIgnoredResources.remove(url)) {
incModificationCount();
fireExternalResourceChanged();
}
}
@Override
public boolean isIgnoredResource(@NotNull String url) {
if (myIgnoredResources.contains(url)) {
return true;
}
// ensure ignored resources are loaded
myStandardResources.getValue();
return myStandardIgnoredResources.contains(url) || isImplicitNamespaceDescriptor(url);
}
private static boolean isImplicitNamespaceDescriptor(@NotNull String url) {
for (ImplicitNamespaceDescriptorProvider provider : ImplicitNamespaceDescriptorProvider.EP_NAME.getExtensions()) {
if (provider.getNamespaceDescriptor(null, url, null) != null) {
return true;
}
}
return false;
}
@Override
public String[] getIgnoredResources() {
// ensure ignored resources are loaded
myStandardResources.getValue();
if (myIgnoredResources.isEmpty()) {
return ArrayUtil.toStringArray(myStandardIgnoredResources);
}
Set set = new THashSet(myIgnoredResources.size() + myStandardIgnoredResources.size());
set.addAll(myIgnoredResources);
set.addAll(myStandardIgnoredResources);
return ArrayUtil.toStringArray(set);
}
@Override
public long getModificationCount(@NotNull Project project) {
return getProjectResources(project).getModificationCount();
}
@Nullable
@Override
public Element getState() {
Element element = new Element("state");
Set urls = new TreeSet();
for (Map map : myResources.values()) {
urls.addAll(map.keySet());
}
for (String url : urls) {
if (url == null) {
continue;
}
String location = getResourceLocation(url);
if (location == null) {
continue;
}
Element e = new Element(RESOURCE_ELEMENT);
e.setAttribute(URL_ATTR, url);
e.setAttribute(LOCATION_ATTR, location.replace(File.separatorChar, '/'));
element.addContent(e);
}
myIgnoredResources.removeAll(myStandardIgnoredResources);
for (String ignoredResource : myIgnoredResources) {
Element e = new Element(IGNORED_RESOURCE_ELEMENT);
e.setAttribute(URL_ATTR, ignoredResource);
element.addContent(e);
}
if (myDefaultHtmlDoctype != null && !HTML5_DOCTYPE_ELEMENT.equals(myDefaultHtmlDoctype)) {
Element e = new Element(HTML_DEFAULT_DOCTYPE_ELEMENT);
e.setText(myDefaultHtmlDoctype);
element.addContent(e);
}
if (myXMLSchemaVersion != XMLSchemaVersion.XMLSchema_1_0) {
Element e = new Element(XML_SCHEMA_VERSION);
e.setText(myXMLSchemaVersion.toString());
element.addContent(e);
}
if (myCatalogPropertiesFile != null) {
Element properties = new Element(CATALOG_PROPERTIES_ELEMENT);
properties.setText(myCatalogPropertiesFile);
element.addContent(properties);
}
ReplacePathToMacroMap macroReplacements = new ReplacePathToMacroMap();
PathMacrosImpl.getInstanceEx().addMacroReplacements(macroReplacements);
macroReplacements.substitute(element, SystemInfo.isFileSystemCaseSensitive);
return element;
}
@Override
public void loadState(Element state) {
ExpandMacroToPathMap macroExpands = new ExpandMacroToPathMap();
PathMacrosImpl.getInstanceEx().addMacroExpands(macroExpands);
macroExpands.substitute(state, SystemInfo.isFileSystemCaseSensitive);
incModificationCount();
for (Element element : state.getChildren(RESOURCE_ELEMENT)) {
String url = element.getAttributeValue(URL_ATTR);
if (!StringUtil.isEmpty(url)) {
addSilently(url, DEFAULT_VERSION, element.getAttributeValue(LOCATION_ATTR).replace('/', File.separatorChar));
}
}
myIgnoredResources.clear();
for (Element element : state.getChildren(IGNORED_RESOURCE_ELEMENT)) {
addIgnoredSilently(element.getAttributeValue(URL_ATTR));
}
Element child = state.getChild(HTML_DEFAULT_DOCTYPE_ELEMENT);
if (child != null) {
String text = child.getText();
if (FileUtil.toSystemIndependentName(text).endsWith(".jar!/resources/html5-schema/html5.rnc")) {
text = HTML5_DOCTYPE_ELEMENT;
}
myDefaultHtmlDoctype = text;
}
Element schemaElement = state.getChild(XML_SCHEMA_VERSION);
if (schemaElement != null) {
String text = schemaElement.getText();
myXMLSchemaVersion = XMLSchemaVersion.XMLSchema_1_1.toString().equals(text) ? XMLSchemaVersion.XMLSchema_1_1 : XMLSchemaVersion.XMLSchema_1_0;
}
Element catalogElement = state.getChild(CATALOG_PROPERTIES_ELEMENT);
if (catalogElement != null) {
myCatalogPropertiesFile = catalogElement.getTextTrim();
}
}
@Override
public void addExternalResourceListener(ExternalResourceListener listener) {
myListeners.add(listener);
}
@Override
public void removeExternalResourceListener(ExternalResourceListener listener) {
myListeners.remove(listener);
}
private void fireExternalResourceChanged() {
for (ExternalResourceListener listener : myListeners) {
listener.externalResourceChanged();
}
incModificationCount();
}
Collection> getStandardResources() {
return myStandardResources.getValue().values();
}
private static final NotNullLazyKey INSTANCE_CACHE = ServiceManager.createLazyKey(ExternalResourceManagerExImpl.class);
private static ExternalResourceManagerExImpl getProjectResources(Project project) {
return INSTANCE_CACHE.getValue(project);
}
@Override
@NotNull
public String getDefaultHtmlDoctype(@NotNull Project project) {
final String doctype = getProjectResources(project).myDefaultHtmlDoctype;
if (XmlUtil.XHTML_URI.equals(doctype)) {
return XmlUtil.XHTML4_SCHEMA_LOCATION;
}
else if (HTML5_DOCTYPE_ELEMENT.equals(doctype)) {
return Html5SchemaProvider.getHtml5SchemaLocation();
}
else {
return doctype;
}
}
@Override
public void setDefaultHtmlDoctype(@NotNull String defaultHtmlDoctype, @NotNull Project project) {
getProjectResources(project).setDefaultHtmlDoctype(defaultHtmlDoctype);
}
@Override
public XMLSchemaVersion getXmlSchemaVersion(@NotNull Project project) {
return getProjectResources(project).myXMLSchemaVersion;
}
@Override
public void setXmlSchemaVersion(XMLSchemaVersion version, @NotNull Project project) {
getProjectResources(project).myXMLSchemaVersion = version;
fireExternalResourceChanged();
}
@Override
public String getCatalogPropertiesFile() {
return myCatalogPropertiesFile;
}
@Override
public void setCatalogPropertiesFile(String filePath) {
myCatalogManager = null;
myCatalogPropertiesFile = filePath;
incModificationCount();
}
@Override
public MultiMap getUrlsByNamespace(Project project) {
return CachedValuesManager.getManager(project).getCachedValue(project, myUrlByNamespaceProvider);
}
@Nullable
private XMLCatalogManager getCatalogManager() {
if (myCatalogManager == null && myCatalogPropertiesFile != null) {
myCatalogManager = new XMLCatalogManager(myCatalogPropertiesFile);
}
return myCatalogManager;
}
private void setDefaultHtmlDoctype(String defaultHtmlDoctype) {
incModificationCount();
if (Html5SchemaProvider.getHtml5SchemaLocation().equals(defaultHtmlDoctype)) {
myDefaultHtmlDoctype = HTML5_DOCTYPE_ELEMENT;
}
else {
myDefaultHtmlDoctype = defaultHtmlDoctype;
}
fireExternalResourceChanged();
}
@TestOnly
public static void registerResourceTemporarily(final String url, final String location, Disposable disposable) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
getInstance().addResource(url, location);
}
});
Disposer.register(disposable, new Disposable() {
@Override
public void dispose() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
getInstance().removeResource(url);
}
});
}
});
}
static class Resource {
private final String myFile;
private final ClassLoader myClassLoader;
private final Class myClass;
private volatile String myResolvedResourcePath;
Resource(String _file, Class _class, ClassLoader _classLoader) {
myFile = _file;
myClass = _class;
myClassLoader = _classLoader;
}
Resource(String _file, Resource baseResource) {
this(_file, baseResource.myClass, baseResource.myClassLoader);
}
String directoryName() {
int i = myFile.lastIndexOf('/');
return i > 0 ? myFile.substring(0, i) : myFile;
}
@Nullable
String getResourceUrl() {
String resolvedResourcePath = myResolvedResourcePath;
if (resolvedResourcePath != null) return resolvedResourcePath;
final URL resource = myClass == null ? myClassLoader.getResource(myFile) : myClass.getResource(myFile);
if (resource == null) {
String message = "Cannot find standard resource. filename:" + myFile + " class=" + myClass + ", classLoader:" + myClassLoader;
if (ApplicationManager.getApplication().isUnitTestMode()) {
LOG.error(message);
}
else {
LOG.warn(message);
}
myResolvedResourcePath = null;
return null;
}
String path = FileUtil.unquote(resource.toString());
// this is done by FileUtil for windows
path = path.replace('\\','/');
myResolvedResourcePath = path;
return path;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Resource resource = (Resource)o;
if (myClassLoader != resource.myClassLoader) return false;
if (myClass != resource.myClass) return false;
if (myFile != null ? !myFile.equals(resource.myFile) : resource.myFile != null) return false;
return true;
}
@Override
public int hashCode() {
return myFile.hashCode();
}
@Override
public String toString() {
return myFile + " for " + myClassLoader;
}
}
}