/******************************************************************************
* Copyright (c) 2016 Oracle
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Konstantin Komissarchik - initial implementation and ongoing maintenance
******************************************************************************/
package org.eclipse.sapphire.modeling.xml.schema;
import java.io.File;
import java.lang.ref.SoftReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.sapphire.LoggingService;
import org.eclipse.sapphire.Sapphire;
import org.eclipse.sapphire.modeling.xml.dtd.DtdParser;
import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
/**
* @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a>
*/
@SuppressWarnings( "restriction" )
public final class XmlDocumentSchemasCache
{
private static final XmlDocumentSchema EMPTY_SCHEMA = ( new XmlDocumentSchema.Factory() ).create();
private static final Map<String,SoftReference<XmlDocumentSchema>> cache
= new HashMap<String,SoftReference<XmlDocumentSchema>>();
public static XmlDocumentSchema getSchema( final String location )
{
return getSchema( null, null, location );
}
public static XmlDocumentSchema getSchema( final String referer,
final String publicId,
final String systemId )
{
if( publicId == null && systemId == null )
{
throw new IllegalArgumentException();
}
String location = URIResolverPlugin.createResolver().resolve( referer, publicId, systemId );
if( location == null )
{
if( systemId != null )
{
location = systemId;
}
else if( publicId != null && ! publicId.startsWith( "-//" ) )
{
location = publicId;
}
}
if( location == null )
{
return EMPTY_SCHEMA;
}
URL url = null;
try
{
url = new URL( location );
}
catch( MalformedURLException e )
{
if( referer != null )
{
try
{
url = ( new File( new File( referer ).getParentFile(), location ) ).toURI().toURL();
location = url.toString();
}
catch( MalformedURLException ex )
{
// We tried.
}
}
}
if( url == null )
{
return EMPTY_SCHEMA;
}
XmlDocumentSchema schema = null;
synchronized( XmlDocumentSchemasCache.class )
{
final SoftReference<XmlDocumentSchema> ref = cache.get( location );
if( ref != null )
{
schema = ref.get();
if( schema == null )
{
cache.remove( location );
}
}
}
if( schema == null )
{
try
{
if( location.endsWith( "dtd" ) )
{
schema = DtdParser.parse( url );
}
else
{
final XmlDocumentSchemaParser.Resolver resolver = new XmlDocumentSchemaParser.Resolver()
{
@Override
public URL resolve( final String location )
{
URL schemaLocationUrl = null;
try
{
schemaLocationUrl = new URL( URIResolverPlugin.createResolver().resolve( referer, null, location ) );
}
catch( MalformedURLException e )
{
if( referer != null )
{
try
{
schemaLocationUrl = ( new File( new File( referer ).getParentFile(), location ) ).toURI().toURL();
}
catch( MalformedURLException ex )
{
throw new RuntimeException( ex );
}
}
}
if( schemaLocationUrl == null )
{
throw new IllegalArgumentException();
}
return schemaLocationUrl;
}
};
schema = XmlDocumentSchemaParser.parse( url, systemId, resolver );
}
}
catch( Exception e )
{
Sapphire.service( LoggingService.class ).log( e );
schema = EMPTY_SCHEMA;
}
synchronized( XmlDocumentSchemasCache.class )
{
final SoftReference<XmlDocumentSchema> ref = new SoftReference<XmlDocumentSchema>( schema );
cache.put( location, ref );
}
}
return schema;
}
}