EMXProxyResolvingResourceSet.java

package org.andromda.repositories.emf.uml22;

import java.util.Set;
import java.util.TreeSet;
import org.apache.log4j.Logger;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;

/**
 * Special resource set implementation that can resolve proxies
 * created by Rational Software Modeler. RSM uses a special syntax
 * (e.g. "resource.emx#someXmiId?someNonstandardString") that cannot
 * be resolved by standard EMF resource sets.
 *
 * @author Matthias Bohlen
 * @author Bob Fields Check for timeouts only once, add logger
 *
 */
public class EMXProxyResolvingResourceSet extends ResourceSetImpl
{
    /**
     * The logger instance.
     */
    private static final Logger logger = Logger.getLogger(EMXProxyResolvingResourceSet.class);

    /**
     *
     */
    private static Set<String> connectExceptions = new TreeSet<String>();
    /**
     * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#getEObject(org.eclipse.emf.common.util.URI, boolean)
     */
    public EObject getEObject(URI uri, boolean loadOnDemand)
    {
        EObject possiblyResolvedObject = null;
        // We see ConnectExceptions when loading metamodels behind a proxy server. Don't try more than once.
        // No need to validate external schema elements, it's just a performance drag.
        if (connectExceptions.contains(uri.toString()))
        {
            return possiblyResolvedObject;
        }
        long now = System.currentTimeMillis();
        try
        {
            // Allow both UML2 v2 and v3+ profile references. Changed from Standard.profile.uml to StandardL2.profile.uml and StandardL3.profile.uml in v3
            //if (uri.toString().contains("Standard.profile.uml"))
            //{
                /*String newUri = uri.toString().replace("Standard.profile.uml", "StandardL2.profile.uml");
                possiblyResolvedObject = super.getEObject(URI.createURI(newUri), loadOnDemand);*/
                //uri = URI.createURI(uri.toString().replace("Standard.profile.uml", "StandardL3.profile.uml"));
            //}
            possiblyResolvedObject = super.getEObject(uri, loadOnDemand);
        }
        catch (Exception e)
        {
            // This will point out invalid model references....
            if (uri.toString().indexOf('?')<0)
            {
                if (e.getMessage().contains("FileNotFoundException"))
                {
                    // MagicDraw and Standard Profiles generally not needed, exporting them takes lots of space
                    // Don't need entire stack trace if referenced file is not found, message is enough.
                    logger.warn("Referenced model FileNotFound: " + uri + " " + (System.currentTimeMillis() - now) + " ms: " +
                            uri.toString() + " " + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage()));
                }
                else
                {
                    logger.error("Could not load referenced model uri " + " " + (System.currentTimeMillis() - now) + "ms: " +
                            uri.toString() + " " + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage()), e.getCause());
                }
            }
            if (!connectExceptions.contains(uri.toString()))
            {
                connectExceptions.add(uri.toString());
            }
        }
        if (possiblyResolvedObject == null)
        {
            // if it is still a proxy, try this special fix for RSM:
            String uriString = uri.toString();
            int separatorIndex = uriString.lastIndexOf('?');
            if (separatorIndex > 0)
            {
                uriString = uriString.substring(0, separatorIndex);
                if (!connectExceptions.contains(uriString))
                {
                    try
                    {
                        possiblyResolvedObject = super.getEObject(URI.createURI(uriString), loadOnDemand);
                    }
                    catch (Exception e)
                    {
                        // No need to log this - it doesn't matter for andromda anyway.
                        //logger.warn("ConnectException "  + (System.currentTimeMillis() - now) + "ms for uri " + uriString);
                        if (!connectExceptions.contains(uriString))
                        {
                            connectExceptions.add(uri.toString());
                        }
                    }
                }
            }
        }
        return possiblyResolvedObject;
    }
}